diff --git a/packages/client-node/.env.sample b/packages/client-node/.env.sample new file mode 100644 index 00000000..8c725271 --- /dev/null +++ b/packages/client-node/.env.sample @@ -0,0 +1,2 @@ +# See README +RPC_WS="172.19.0.1:9944" diff --git a/packages/client-node/.gitignore b/packages/client-node/.gitignore new file mode 100644 index 00000000..4c49bd78 --- /dev/null +++ b/packages/client-node/.gitignore @@ -0,0 +1 @@ +.env diff --git a/packages/client-node/README.md b/packages/client-node/README.md index 3946797c..90f95c01 100644 --- a/packages/client-node/README.md +++ b/packages/client-node/README.md @@ -9,3 +9,19 @@ Use your favorite package manager (e.g. yarn) and install package `@logion/clien ## Usage See [core client](../client/README.md). + +## Integration tests + +### Pre-requisites + +Below steps must be executed only if you did not yet create the `logion-test` network. + +- Create `logion-test` network: `docker network create logion-test` +- Get network's gateway IP address: `docker network inspect logion-test | jq '.[0].IPAM.Config[0].Gateway'` +- Set `RPC_WS` variable in `.env` file (see `.env.sample` for an example) with the above IP address + +### Running the tests + +- Start the Logion chain locally (see [here](https://github.com/logion-network/logion-collator/?tab=readme-ov-file#test-locally)) +- In another terminal, run the tests: `yarn integration-test` +- Stop Zombienet diff --git a/packages/client-node/docker-compose.yml b/packages/client-node/docker-compose.yml index 8b0b3799..da0e5adb 100644 --- a/packages/client-node/docker-compose.yml +++ b/packages/client-node/docker-compose.yml @@ -1,23 +1,21 @@ -version: "3.6" +networks: + default: + name: logion-test + external: true + services: # ----------------------------------------- Logion node 1 -------------------------------------------------------------- private-database1: image: logionnetwork/logion-postgres:${PG_TAG:-latest} environment: - POSTGRES_PASSWORD=secret - node1: - image: logionnetwork/logion-node:${NODE_TAG:-latest} - environment: - - NODE_KEY=c12b6d18942f5ee8528c8e2baf4e147b5c5c18710926ea492d09cbd9f6c9f82a - - CUSTOM_OPTIONS=--alice --no-mdns --rpc-external --rpc-cors all - - CHAIN_SPEC=test backend1: image: logionnetwork/logion-backend:${BACKEND_TAG:-latest} environment: - JWT_SECRET=c12b6d18942f5ee8528c8e2baf4e147b5c5c18710926ea492d09cbd9f6c9f82a - JWT_ISSUER=12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2 - TYPEORM_HOST=private-database1 - - WS_PROVIDER_URL=ws://node1:9944 + - WS_PROVIDER_URL=ws://$RPC_WS - OWNER=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY - DIRECTORY_URL=http://directory:8080 - SMTP_ENABLED=false @@ -27,24 +25,21 @@ services: - IPFS_MAX_REPLICA=2 - ENC_PASSWORD=test depends_on: - - node1 - private-database1 - ipfs-cluster1 frontend1: image: logionnetwork/logion-frontend:${FRONTEND_TAG:-latest} ports: - 127.0.0.1:8080:80 - - 127.0.0.1:9944:9944 volumes: - ./front_config.js:/usr/share/nginx/html/config.js - ./front_web1.conf:/etc/nginx/conf.d/default.conf depends_on: - backend1 - - node1 environment: - CERTBOT_EMAIL=user1@invalid.domain - BACKEND_HOST_PORT=backend1:8080 - - NODE_HOST_PORT=node1:9944 + - NODE_HOST_PORT=$RPC_WS ipfs1: image: ipfs/go-ipfs:v0.12.0 ports: @@ -68,21 +63,13 @@ services: image: logionnetwork/logion-postgres:${PG_TAG:-latest} environment: - POSTGRES_PASSWORD=secret - node2: - image: logionnetwork/logion-node:${NODE_TAG:-latest} - environment: - - NODE_KEY=6ce3be907dbcabf20a9a5a60a712b4256a54196000a8ed4050d352bc113f8c58 - - CUSTOM_OPTIONS=--bob --no-mdns --bootnodes /dns4/node1/tcp/30333/p2p/12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2 --rpc-external --rpc-cors all - - CHAIN_SPEC=test - depends_on: - - node1 backend2: image: logionnetwork/logion-backend:${BACKEND_TAG:-latest} environment: - JWT_SECRET=6ce3be907dbcabf20a9a5a60a712b4256a54196000a8ed4050d352bc113f8c58 - JWT_ISSUER=12D3KooWQYV9dGMFoRzNStwpXztXaBUjtPqi6aU76ZgUriHhKust - TYPEORM_HOST=private-database2 - - WS_PROVIDER_URL=ws://node2:9944 + - WS_PROVIDER_URL=ws://$RPC_WS - OWNER=5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty - DIRECTORY_URL=http://directory:8080 - SMTP_ENABLED=false @@ -92,24 +79,21 @@ services: - IPFS_MAX_REPLICA=2 - ENC_PASSWORD=test depends_on: - - node2 - private-database2 - ipfs-cluster2 frontend2: image: logionnetwork/logion-frontend:${FRONTEND_TAG:-latest} ports: - 127.0.0.1:8081:80 - - 127.0.0.1:9945:9944 volumes: - ./front_config.js:/usr/share/nginx/html/config.js - ./front_web2.conf:/etc/nginx/conf.d/default.conf depends_on: - backend2 - - node2 environment: - CERTBOT_EMAIL=user2@invalid.domain - BACKEND_HOST_PORT=backend2:8080 - - NODE_HOST_PORT=node2:9944 + - NODE_HOST_PORT=$RPC_WS ipfs2: image: ipfs/go-ipfs:v0.12.0 volumes: @@ -132,21 +116,13 @@ services: image: logionnetwork/logion-postgres:${PG_TAG:-latest} environment: - POSTGRES_PASSWORD=secret - node3: - image: logionnetwork/logion-node:${NODE_TAG:-latest} - environment: - - NODE_KEY=3a9d5b35b9fb4c42aafadeca046f6bf56107bd2579687f069b42646684b94d9e - - CUSTOM_OPTIONS=--charlie --no-mdns --bootnodes /dns4/node1/tcp/30333/p2p/12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2 --rpc-external --rpc-cors all - - CHAIN_SPEC=test - depends_on: - - node1 backend3: image: logionnetwork/logion-backend:${BACKEND_TAG:-latest} environment: - JWT_SECRET=3a9d5b35b9fb4c42aafadeca046f6bf56107bd2579687f069b42646684b94d9e - JWT_ISSUER=12D3KooWJvyP3VJYymTqG7eH4PM5rN4T2agk5cdNCfNymAqwqcvZ - TYPEORM_HOST=private-database3 - - WS_PROVIDER_URL=ws://node3:9944 + - WS_PROVIDER_URL=ws://$RPC_WS - OWNER=5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y - DIRECTORY_URL=http://directory:8080 - SMTP_ENABLED=false @@ -156,24 +132,21 @@ services: - IPFS_MAX_REPLICA=2 - ENC_PASSWORD=test depends_on: - - node3 - private-database3 - ipfs-cluster3 frontend3: image: logionnetwork/logion-frontend:${FRONTEND_TAG:-latest} ports: - 127.0.0.1:8082:80 - - 127.0.0.1:9946:9944 volumes: - ./front_config.js:/usr/share/nginx/html/config.js - ./front_web3.conf:/etc/nginx/conf.d/default.conf depends_on: - backend3 - - node3 environment: - CERTBOT_EMAIL=user3@invalid.domain - BACKEND_HOST_PORT=backend3:8080 - - NODE_HOST_PORT=node3:9944 + - NODE_HOST_PORT=$RPC_WS ipfs3: image: ipfs/go-ipfs:v0.12.0 volumes: @@ -205,8 +178,7 @@ services: environment: - JWT_SECRET=c12b6d18942f5ee8528c8e2baf4e147b5c5c18710926ea492d09cbd9f6c9f82a - JWT_ISSUER=12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2 - - WS_PROVIDER_URL=ws://node1:9944 + - WS_PROVIDER_URL=ws://$RPC_WS - TYPEORM_HOST=directory-database depends_on: - - node1 - directory-database diff --git a/packages/client-node/front_web1.conf b/packages/client-node/front_web1.conf index beac9e76..313ef744 100644 --- a/packages/client-node/front_web1.conf +++ b/packages/client-node/front_web1.conf @@ -26,20 +26,3 @@ server { root /usr/share/nginx/html; } } - -server { - listen 9944; - listen [::]:9944; - server_name localhost; - - location / { - proxy_pass http://node1:9944; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } -} diff --git a/packages/client-node/front_web2.conf b/packages/client-node/front_web2.conf index 615b0619..bdf38862 100644 --- a/packages/client-node/front_web2.conf +++ b/packages/client-node/front_web2.conf @@ -26,20 +26,3 @@ server { root /usr/share/nginx/html; } } - -server { - listen 9944; - listen [::]:9944; - server_name localhost; - - location / { - proxy_pass http://node2:9944; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } -} diff --git a/packages/client-node/front_web3.conf b/packages/client-node/front_web3.conf index bcbe39a9..c3bc5d52 100644 --- a/packages/client-node/front_web3.conf +++ b/packages/client-node/front_web3.conf @@ -26,20 +26,3 @@ server { root /usr/share/nginx/html; } } - -server { - listen 9944; - listen [::]:9944; - server_name localhost; - - location / { - proxy_pass http://node3:9944; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } -} diff --git a/packages/client-node/integration/Balance.ts b/packages/client-node/integration/Balance.ts index 1f23519a..d417aeb3 100644 --- a/packages/client-node/integration/Balance.ts +++ b/packages/client-node/integration/Balance.ts @@ -1,50 +1,55 @@ import { Numbers, CoinBalance, Lgnt } from "@logion/node-api"; import { BalanceState, waitFor } from "@logion/client"; -import { State, REQUESTER_ADDRESS } from "./Utils.js"; -import { ALICE } from "./Utils.js"; +import { State } from "./Utils.js"; export async function transfers(state: State) { - const { client, signer, aliceAccount, requesterAccount } = state; + const { client, signer, alice, requesterAccount } = state; // Alice transfers to user. - const aliceClient = client.withCurrentAddress(aliceAccount) + const aliceClient = client.withCurrentAccount(alice.account) let aliceState = await aliceClient.balanceState(); - checkBalance(aliceState, "99.99k"); + let aliceSnapshot = takeSnapshot(aliceState); expect(aliceState.transactions.length).toBe(0); aliceState = await aliceState.transfer({ signer, amount: Lgnt.from(5000n), - destination: REQUESTER_ADDRESS + destination: requesterAccount, }); - checkBalance(aliceState, "94.99k"); + checkBalanceDelta(aliceState, "-4.99k", aliceSnapshot); aliceState = await waitFor({ producer: async state => state ? await state.refresh() : aliceState, - predicate: state => state.transactions.length === 2, + predicate: state => { + if (state.transactions.length > 0) { + const transaction = state.transactions[0]; + return transaction.pallet === "balances" && transaction.method === "transferKeepAlive" + } else { + return false; + } + } }); expect(aliceState.transactions[0].fees.inclusion).toBeGreaterThan(0); expect(aliceState.transactions[0].fees.storage).toBeUndefined(); expect(aliceState.transactions[0].transferValue).toBe(Lgnt.fromPrefixedNumber(new Numbers.PrefixedNumber("5", Numbers.KILO)).toString()); // User transfers to Alice. - const userClient = client.withCurrentAddress(requesterAccount) + const userClient = client.withCurrentAccount(requesterAccount) let userState = await userClient.balanceState(); + aliceSnapshot = takeSnapshot(await aliceState.refresh()); + checkBalance(userState, "5.00k"); userState = await userState.transfer({ signer, amount: Lgnt.from(2000n), - destination: ALICE + destination: alice.account, }); checkBalance(userState, "2.99k"); - // TODO: the balance of a LO is not stable as it increases with block rewards - // this integration test should be rewritten with regular users. - // // Alice checks her balance. - // aliceState = await aliceState.refresh(); - // checkBalance(aliceState, "97.00k"); // is sometimes 96.99k depending on block reward. + aliceState = await aliceState.refresh(); + checkBalanceDelta(aliceState, "2.00k", aliceSnapshot); } export function checkBalance(balanceState: BalanceState, expectedValue: string) { @@ -52,9 +57,29 @@ export function checkBalance(balanceState: BalanceState, expectedValue: string) checkCoinBalance(balance, expectedValue); } +export function takeSnapshot(balanceState: BalanceState): CoinBalance { + return balanceState.balances[0]; +} + +export function checkBalanceDelta(current: BalanceState, expectedDelta: string, previous: CoinBalance) { + checkCoinBalanceDelta(takeSnapshot(current), expectedDelta, previous); +} + +export function checkCoinBalanceDelta(current: CoinBalance, expectedDelta: string, previous: CoinBalance) { + expect(current.coin).toEqual(previous.coin); + const delta: CoinBalance = { + coin: current.coin, + available: current.available.subtract(previous.available), + reserved: current.reserved.subtract(previous.reserved), + total: current.total.subtract(previous.total), + level: current.level - previous.level, + } + checkCoinBalance(delta, expectedDelta); +} + export function checkCoinBalance(balance: CoinBalance, expectedValue: string) { const formatted = formatBalance(balance); - expect(formatted).toEqual(expectedValue) + expect(expectedValue).toEqual(formatted) } export function formatBalance(balance: CoinBalance): string { @@ -62,28 +87,28 @@ export function formatBalance(balance: CoinBalance): string { } export async function transferAndCannotPayFees(state: State) { - const { client, signer, requesterAccount } = state; + const { client, signer, requesterAccount, alice } = state; - const requesterClient = client.withCurrentAddress(requesterAccount) + const requesterClient = client.withCurrentAccount(requesterAccount) let balanceState = await requesterClient.balanceState(); await expectAsync(balanceState.transfer({ signer, amount: Lgnt.from(1n), - destination: ALICE, + destination: alice.account, })).toBeRejectedWithError("Not enough funds available to pay fees"); } export async function transferWithInsufficientFunds(state: State) { - const { client, signer, aliceAccount } = state; + const { client, signer, alice, requesterAccount } = state; // Alice transfers to user. - const aliceClient = client.withCurrentAddress(aliceAccount) + const aliceClient = client.withCurrentAccount(alice.account) let aliceState = await aliceClient.balanceState(); await expectAsync(aliceState.transfer({ signer, amount: Lgnt.fromCanonicalPrefixedNumber(aliceState.balances[0].available).add(Lgnt.from(1)), - destination: REQUESTER_ADDRESS + destination: requesterAccount, })).toBeRejectedWithError("Insufficient balance"); } diff --git a/packages/client-node/integration/DirectLocOpen.ts b/packages/client-node/integration/DirectLocOpen.ts index b85b83ac..fc1bc440 100644 --- a/packages/client-node/integration/DirectLocOpen.ts +++ b/packages/client-node/integration/DirectLocOpen.ts @@ -1,8 +1,7 @@ import { NodeFile } from "../src/index.js"; import { State, - initRequesterBalance, - TEST_LOGION_CLIENT_CONFIG, + initAccountBalance, DIRECT_REQUESTER_ADDRESS, findWithLegalOfficerClient, } from "./Utils.js"; @@ -24,16 +23,16 @@ import { import { Lgnt, UUID } from "@logion/node-api"; export async function openIdentityLoc(state: State): Promise { - const { directRequesterAccount, signer, alice, aliceAccount } = state; - const client = state.client.withCurrentAddress(directRequesterAccount); + const { directRequesterAccount, signer, alice } = state; + const client = state.client.withCurrentAccount(directRequesterAccount); let locsState = await client.locsState(); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, signer, directRequesterAccount.address); + await initAccountBalance(state, directRequesterAccount); const items = provideItems("identity", []); const openLoc = await locsState.openIdentityLoc({ description: "Direct Identity", - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, template: "a-template", legalFee: Lgnt.fromCanonical(15n), files: items.files, @@ -56,7 +55,7 @@ export async function openIdentityLoc(state: State): Promise { }); checkData(openLoc.data(), items); - const aliceClient = state.client.withCurrentAddress(aliceAccount); + const aliceClient = state.client.withCurrentAccount(alice.account); let aliceOpenLoc = await findWithLegalOfficerClient(aliceClient, openLoc) as OpenLoc; aliceOpenLoc = await waitFor({ producer: prev => prev ? prev.refresh() as Promise : aliceOpenLoc.refresh() as Promise, @@ -69,12 +68,12 @@ export async function openIdentityLoc(state: State): Promise { export async function openTransactionLoc(state: State, linkedLoc: UUID): Promise { const { directRequesterAccount, signer, alice } = state; - const client = state.client.withCurrentAddress(directRequesterAccount); + const client = state.client.withCurrentAccount(directRequesterAccount); let locsState = await client.locsState(); const items = provideItems("transaction", [ linkedLoc ]); const openLoc = await locsState.openTransactionLoc({ description: "Direct Transaction", - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, template: "a-template", legalFee: Lgnt.fromCanonical(15n), files: items.files, @@ -98,12 +97,12 @@ function allItemsHaveAddedOn(loc: LocData) { export async function openCollectionLoc(state: State, linkedLoc1: UUID, linkedLoc2: UUID): Promise { const { directRequesterAccount, signer, alice } = state; - const client = state.client.withCurrentAddress(directRequesterAccount); + const client = state.client.withCurrentAccount(directRequesterAccount); let locsState = await client.locsState(); const items = provideItems("collection", [ linkedLoc1, linkedLoc2 ]); const openLoc = await locsState.openCollectionLoc({ description: "Direct Collection", - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, template: "a-template", legalFee: Lgnt.fromCanonical(15n), files: items.files, @@ -139,9 +138,10 @@ function checkData(data: LocData, items: ItemsParams) { expect(data.fees.legalFee?.canonical).toEqual(15n) expect(data.template).toEqual("a-template") expect(data.requesterLocId).toBeUndefined(); - expect(data.requesterAddress?.address).toEqual(DIRECT_REQUESTER_ADDRESS); - expect(data.requesterAddress?.type).toEqual("Polkadot"); - expect(data.ownerAddress).toEqual(ALICE); + expect(data.requesterAccountId?.address).toEqual(DIRECT_REQUESTER_ADDRESS); + expect(data.requesterAccountId?.type).toEqual("Polkadot"); + expect(data.ownerAccountId.address).toEqual(ALICE); + expect(data.ownerAccountId.type).toEqual("Polkadot"); expect(data.files.length).toEqual(items.files.length); expect(data.metadata.length).toEqual(items.metadata.length); diff --git a/packages/client-node/integration/Fees.ts b/packages/client-node/integration/Fees.ts index c714d2af..9fa881ae 100644 --- a/packages/client-node/integration/Fees.ts +++ b/packages/client-node/integration/Fees.ts @@ -1,10 +1,9 @@ -import { ALICE } from "./Utils.js"; -import { State, REQUESTER_ADDRESS } from "./Utils.js"; +import { State } from "./Utils.js"; export async function fees(state: State) { - const client = state.client; + const { client, requesterAccount, alice } = state; const api = client.logionApi; - const submittable = api.polkadot.tx.balances.transferAllowDeath(ALICE, "10000000"); - const fees = await client.public.fees.estimateWithoutStorage({ origin: REQUESTER_ADDRESS, submittable }); - expect(fees.totalFee.canonical).toBe(1549504589051721312n); + const submittable = api.polkadot.tx.balances.transferAllowDeath(alice.account.address, "10000000"); + const fees = await client.public.fees.estimateWithoutStorage({ origin: requesterAccount, submittable }); + expect(fees.totalFee.canonical).toBe(1526123495430309312n); } diff --git a/packages/client-node/integration/InvitedContributors.ts b/packages/client-node/integration/InvitedContributors.ts index 74b714f3..06c85aef 100644 --- a/packages/client-node/integration/InvitedContributors.ts +++ b/packages/client-node/integration/InvitedContributors.ts @@ -11,21 +11,20 @@ import { } from "@logion/client"; import { State, - initRequesterBalance, - TEST_LOGION_CLIENT_CONFIG, + initAccountBalance, INVITED_CONTRIBUTOR_ADDRESS } from "./Utils.js"; import { NodeFile } from "../src/index.js"; export async function invitedContributors(state: State) { - const { alice, aliceAccount, invitedContributorAccount, newAccount, signer } = state; + const { alice, invitedContributorAccount, newAccount, signer } = state; - const invitedContributorClient = state.client.withCurrentAddress(invitedContributorAccount); + const invitedContributorClient = state.client.withCurrentAccount(invitedContributorAccount); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, signer, INVITED_CONTRIBUTOR_ADDRESS); + await initAccountBalance(state, invitedContributorAccount); let invitedContributorLocsState = await invitedContributorClient.locsState(); const pendingRequest = await invitedContributorLocsState.requestIdentityLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is an invited contributor Identity LOC", userIdentity: { email: "john.doe.trusted@invalid.domain", @@ -44,8 +43,8 @@ export async function invitedContributors(state: State) { }); const invitedContributorIdentityLocId = pendingRequest.data().id; - const aliceClient = state.client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: aliceAccount.address, locTypes: ["Identity"], statuses: ["REVIEW_PENDING"] } }); + const aliceClient = state.client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Identity"], statuses: ["REVIEW_PENDING"] } }); const alicePending = aliceLocs.findById(invitedContributorIdentityLocId) as PendingRequest; const aliceAccepted = await alicePending.legalOfficer.accept(); @@ -59,10 +58,10 @@ export async function invitedContributors(state: State) { }); await aliceOpen.legalOfficer.close({ signer, autoAck: false }) as ClosedLoc; - const requesterClient = state.client.withCurrentAddress(newAccount); + const requesterClient = state.client.withCurrentAccount(newAccount); let userLocsState = await requesterClient.locsState(); let pendingLocRequest = await userLocsState.requestCollectionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "Some LOC with invited contributor", draft: false, legalFee: Lgnt.zero(), @@ -76,7 +75,7 @@ export async function invitedContributors(state: State) { }) as PendingRequest; const collectionLocId = pendingLocRequest.data().id; - aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: aliceAccount.address, locTypes: ["Collection"], statuses: ["REVIEW_PENDING"] } }); + aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Collection"], statuses: ["REVIEW_PENDING"] } }); const alicePendingCollection = aliceLocs.findById(collectionLocId) as PendingRequest; await alicePendingCollection.legalOfficer.accept(); diff --git a/packages/client-node/integration/LegalOfficer.ts b/packages/client-node/integration/LegalOfficer.ts index adb1e785..4a26d13a 100644 --- a/packages/client-node/integration/LegalOfficer.ts +++ b/packages/client-node/integration/LegalOfficer.ts @@ -1,22 +1,20 @@ -import { ALICE, State } from "./Utils.js"; - +import { State } from "./Utils.js"; export async function backendConfig(state: State) { - const { client, requesterAccount } = state; - - const authenticatedClient = client.withCurrentAddress(requesterAccount); - const alice = authenticatedClient.getLegalOfficer(ALICE); - const config = await alice.getConfig(); + const { client, requesterAccount, alice } = state; + const authenticatedClient = client.withCurrentAccount(requesterAccount); + const llo = authenticatedClient.getLegalOfficer(alice.account); + const config = await llo.getConfig(); expect(config.features.iDenfy).toBe(false); expect(config.features.vote).toBe(false); } -export async function workload(state: State, ...legalOfficerAddresses: string[]) { - const { client, requesterAccount } = state; +export async function workload(state: State) { + const { client, requesterAccount, alice, bob } = state; - const authenticatedClient = client.withCurrentAddress(requesterAccount); - for (const address of legalOfficerAddresses) { - const legalOfficer = authenticatedClient.getLegalOfficer(address); + const authenticatedClient = client.withCurrentAccount(requesterAccount); + for (const account of [ alice.account, bob.account ]) { + const legalOfficer = authenticatedClient.getLegalOfficer(account); const workload = await legalOfficer.getWorkload(); expect(workload).toBe(0); } diff --git a/packages/client-node/integration/Loc.ts b/packages/client-node/integration/Loc.ts index 590086ce..2332ceb5 100644 --- a/packages/client-node/integration/Loc.ts +++ b/packages/client-node/integration/Loc.ts @@ -20,21 +20,20 @@ import { import { State, - TEST_LOGION_CLIENT_CONFIG, findWithLegalOfficerClient, - initRequesterBalance, + initAccountBalance, updateConfig } from "./Utils.js"; import { NodeFile } from "../src/index.js"; export async function requestTransactionLoc(state: State, linkTarget: UUID): Promise { - const { alice, aliceAccount, newAccount, signer } = state; - const client = state.client.withCurrentAddress(newAccount); + const { alice, newAccount, signer } = state; + const client = state.client.withCurrentAccount(newAccount); let locsState = await client.locsState(); // Create DRAFT LOC let draftRequest = await locsState.requestTransactionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is a Transaction LOC", draft: true, }) as DraftRequest; @@ -79,8 +78,8 @@ export async function requestTransactionLoc(state: State, linkTarget: UUID): Pro expect(pendingRequest.data().metadata[0].status).toBe("REVIEW_PENDING"); // Rework rejected LOC - const aliceClient = state.client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.address, statuses: [ "REVIEW_PENDING", "OPEN" ], locTypes: [ "Transaction" ] } }); + const aliceClient = state.client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, statuses: [ "REVIEW_PENDING", "OPEN" ], locTypes: [ "Transaction" ] } }); let alicePendingLoc = aliceLocs.findById(pendingRequest.data().id) as PendingRequest; alicePendingLoc = await alicePendingLoc.legalOfficer.reviewMetadata({ nameHash, decision: "REJECT", rejectReason: "Invalid value" }); let aliceRejectedLoc = await alicePendingLoc.legalOfficer.reject("Because.") as RejectedRequest; @@ -193,13 +192,13 @@ export async function requestTransactionLoc(state: State, linkTarget: UUID): Pro } export async function openTransactionLocWithAutoPublish(state: State, linkTarget: UUID) { - const { alice, aliceAccount, newAccount, signer } = state; - const client = state.client.withCurrentAddress(newAccount); + const { alice, newAccount, signer } = state; + const client = state.client.withCurrentAccount(newAccount); let locsState = await client.locsState(); // Create DRAFT LOC let draftRequest = await locsState.requestTransactionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is a Transaction LOC", draft: true, }) as DraftRequest; @@ -249,8 +248,8 @@ export async function openTransactionLocWithAutoPublish(state: State, linkTarget expect(pendingRequest).toBeInstanceOf(PendingRequest); // Alice accepts all items - const aliceClient = state.client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.address, statuses: [ "REVIEW_PENDING", "OPEN" ], locTypes: [ "Transaction" ] } }); + const aliceClient = state.client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, statuses: [ "REVIEW_PENDING", "OPEN" ], locTypes: [ "Transaction" ] } }); let alicePendingLoc = aliceLocs.findById(pendingRequest.data().id) as PendingRequest; // metadata alicePendingLoc = await alicePendingLoc.legalOfficer.reviewMetadata({ nameHash, decision: "ACCEPT" }); @@ -291,12 +290,12 @@ function checkData(data: LocData, locRequestStatus: LocRequestStatus) { } export async function transactionLocWithCustomLegalFee(state: State) { - const { alice, aliceAccount, newAccount, signer } = state; - const client = state.client.withCurrentAddress(newAccount); + const { alice, newAccount, signer } = state; + const client = state.client.withCurrentAccount(newAccount); let locsState = await client.locsState(); let draftRequest = await locsState.requestTransactionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is a Transaction LOC", draft: true, legalFee: Lgnt.zero(), @@ -307,8 +306,8 @@ export async function transactionLocWithCustomLegalFee(state: State) { // Open LOC let pendingRequest = await draftRequest.submit(); - const aliceClient = state.client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.address, statuses: [ "REVIEW_PENDING", "OPEN" ], locTypes: [ "Transaction" ] } }); + const aliceClient = state.client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, statuses: [ "REVIEW_PENDING", "OPEN" ], locTypes: [ "Transaction" ] } }); let alicePendingLoc = aliceLocs.findById(pendingRequest.data().id) as PendingRequest; await alicePendingLoc.legalOfficer.accept({ signer }) as AcceptedRequest; let acceptedLoc = await pendingRequest.refresh() as AcceptedRequest; @@ -319,15 +318,15 @@ export async function transactionLocWithCustomLegalFee(state: State) { export async function collectionLoc(state: State) { - const { alice, aliceAccount, newAccount, signer } = state; - const client = state.client.withCurrentAddress(newAccount); + const { alice, newAccount, signer } = state; + const client = state.client.withCurrentAccount(newAccount); let locsState = await client.locsState(); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, state.signer, newAccount.address); + await initAccountBalance(state, newAccount); const collectionItemFee = Lgnt.fromCanonical(50n); const pendingRequest = await locsState.requestCollectionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is a Collection LOC", draft: false, valueFee: Lgnt.fromCanonical(100n), @@ -349,8 +348,8 @@ export async function collectionLoc(state: State) { expect(locsState.pendingRequests["Collection"][0].data().status).toBe("REVIEW_PENDING"); const locId = pendingRequest.locId; - const aliceClient = client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.address, locTypes: ["Collection"], statuses: ["REVIEW_PENDING"] } }); + const aliceClient = client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Collection"], statuses: ["REVIEW_PENDING"] } }); let alicePendingRequest = aliceLocs.findById(locId) as PendingRequest; let aliceAcceptedLoc = await alicePendingRequest.legalOfficer.accept(); @@ -418,19 +417,19 @@ export async function collectionLoc(state: State) { export async function collectionLocWithUpload(state: State) { - const { alice, aliceAccount, newAccount, signer } = state; - let client = state.client.withCurrentAddress(newAccount); + const { alice, newAccount, signer } = state; + let client = state.client.withCurrentAccount(newAccount); let locsState = await client.locsState(); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, state.signer, newAccount.address); + await initAccountBalance(state, newAccount); const logionClassificationLocRequest = await locsState.requestTransactionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is the Logion Classification LOC", draft: false, }) as PendingRequest; - let aliceClient = client.withCurrentAddress(aliceAccount); + let aliceClient = client.withCurrentAccount(alice.account); let aliceLogionClassificationLocRequest = await findWithLegalOfficerClient(aliceClient, logionClassificationLocRequest) as PendingRequest; const aliceLogionClassificationAcceptedRequest = await aliceLogionClassificationLocRequest.legalOfficer.accept({ signer }) as AcceptedRequest; const logionClassificationAcceptedRequest = await logionClassificationLocRequest.refresh() as AcceptedRequest; @@ -444,7 +443,7 @@ export async function collectionLocWithUpload(state: State) { locsState = logionClassificationOpenLoc.locsState(); const creativeCommonsLocRequest = await locsState.requestTransactionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is the LOC acting usage of CreativeCommons on logion", draft: false, }) as PendingRequest; @@ -463,12 +462,12 @@ export async function collectionLocWithUpload(state: State) { logionClassificationLoc: logionClassificationOpenLoc.locId, creativeCommonsLoc: creativeCommonsOpenLoc.locId, }) - client = state.client.withCurrentAddress(newAccount); - aliceClient = state.client.withCurrentAddress(aliceAccount); + client = state.client.withCurrentAccount(newAccount); + aliceClient = state.client.withCurrentAccount(alice.account); locsState = await client.locsState(); const pendingRequest = await locsState.requestCollectionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is a Collection LOC with upload", draft: false, valueFee: Lgnt.fromCanonical(100n), @@ -630,10 +629,10 @@ export async function collectionLocWithUpload(state: State) { } export async function otherIdentityLoc(state: State): Promise { - const { alice, aliceAccount, ethereumAccount, signer } = state; + const { alice, ethereumAccount, signer } = state; const sponsorshipId = new UUID(); - const aliceClient = state.client.withCurrentAddress(aliceAccount); + const aliceClient = state.client.withCurrentAccount(alice.account); await aliceClient.sponsorship.sponsor({ sponsorshipId, sponsoredAccount: ethereumAccount.toOtherAccountId(), @@ -641,11 +640,11 @@ export async function otherIdentityLoc(state: State): Promise { signer, }); - const client = state.client.withCurrentAddress(ethereumAccount); + const client = state.client.withCurrentAccount(ethereumAccount); let locsState = await client.locsState(); const pendingRequest = await locsState.requestIdentityLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is an Identity LOC", userIdentity: { email: "john.doe@invalid.domain", @@ -679,8 +678,8 @@ export async function otherIdentityLoc(state: State): Promise { } export async function logionIdentityLoc(state: State) { - const { aliceAccount, signer } = state; - const client = state.client.withCurrentAddress(aliceAccount); + const { alice, signer } = state; + const client = state.client.withCurrentAccount(alice.account); let locsState = await client.locsState(); let openLogionIdentityLoc = await locsState.legalOfficer.createLoc({ diff --git a/packages/client-node/integration/Main.spec.ts b/packages/client-node/integration/Main.spec.ts index a56b2129..063ac6d0 100644 --- a/packages/client-node/integration/Main.spec.ts +++ b/packages/client-node/integration/Main.spec.ts @@ -1,4 +1,4 @@ -import { setupInitialState, State, tearDown, ALICE, BOB } from "./Utils.js"; +import { setupInitialState, State, tearDown } from "./Utils.js"; import { enablesProtection, requestValidIdentity } from "./Protection.js"; import { transferAndCannotPayFees, transfers, transferWithInsufficientFunds } from "./Balance.js"; import { providesVault } from "./Vault.js"; @@ -23,7 +23,7 @@ import { invitedContributors } from "./InvitedContributors.js"; describe("Logion SDK", () => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 1200000; let state: State; @@ -36,7 +36,7 @@ describe("Logion SDK", () => { }); it("fetches workload", async () => { - await workload(state, ALICE, BOB); + await workload(state); }); it("estimates fees", async () => { diff --git a/packages/client-node/integration/Protection.ts b/packages/client-node/integration/Protection.ts index d130d5c2..a795be37 100644 --- a/packages/client-node/integration/Protection.ts +++ b/packages/client-node/integration/Protection.ts @@ -8,9 +8,10 @@ import { OpenLoc, waitFor } from '@logion/client'; -import { initRequesterBalance, State, TEST_LOGION_CLIENT_CONFIG } from "./Utils.js"; +import { initAccountBalance, State } from "./Utils.js"; import { ClosedLoc } from "@logion/client/dist/Loc"; import { LegalOfficerClass } from "@logion/client/dist/Types"; +import debugLog = jasmine.debugLog; export interface IdentityLocs { alice: UUID, @@ -19,10 +20,10 @@ export interface IdentityLocs { } export async function requestValidIdentity(state: State, account: ValidAccountId): Promise { - const { alice, aliceAccount, bob, bobAccount, charlie, charlieAccount } = state - const idByAlice = await createsIdentityLoc(state, account, alice, aliceAccount); - const idByBob = await createsIdentityLoc(state, account, bob, bobAccount); - const idByCharlie = await createsIdentityLoc(state, account, charlie, charlieAccount); + const { alice, bob, charlie } = state + const idByAlice = await createsIdentityLoc(state, account, alice); + const idByBob = await createsIdentityLoc(state, account, bob); + const idByCharlie = await createsIdentityLoc(state, account, charlie); return { alice: idByAlice.data().id, bob: idByBob.data().id, charlie: idByCharlie.data().id } } @@ -34,17 +35,17 @@ export async function enablesProtection(state: State, identityLocs: IdentityLocs async function activateProtection(state: State, identityLocs: IdentityLocs): Promise { const { client, alice, charlie, requesterAccount, signer } = state; - const authenticatedClient = client.withCurrentAddress(requesterAccount); + const authenticatedClient = client.withCurrentAccount(requesterAccount); - console.log("Requesting protection") + debugLog("Requesting protection") const current = await authenticatedClient.protectionState(); expect(current).toBeInstanceOf(NoProtection); if (current instanceof NoProtection) { return await current.activateProtection({ payload: { - legalOfficer1: authenticatedClient.getLegalOfficer(alice.address), - legalOfficer2: authenticatedClient.getLegalOfficer(charlie.address), + legalOfficer1: authenticatedClient.getLegalOfficer(alice.account), + legalOfficer2: authenticatedClient.getLegalOfficer(charlie.account), requesterIdentityLoc1: identityLocs.alice, requesterIdentityLoc2: identityLocs.charlie, }, @@ -55,16 +56,16 @@ async function activateProtection(state: State, identityLocs: IdentityLocs): Pro } } -async function createsIdentityLoc(state: State, account: ValidAccountId, legalOfficer: LegalOfficerClass, legalOfficerAccount: ValidAccountId): Promise { +async function createsIdentityLoc(state: State, account: ValidAccountId, legalOfficer: LegalOfficerClass): Promise { const { client, signer } = state; - console.log("Setting balance of %s", account.address) - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, signer, account.address); + debugLog(`Setting balance of ${ account.address }`) + await initAccountBalance(state, account); - const authenticatedClient = client.withCurrentAddress(account); + const authenticatedClient = client.withCurrentAccount(account); const locsState = await authenticatedClient.locsState(); const pendingRequest = await locsState.requestIdentityLoc({ - legalOfficerAddress: legalOfficer.address, + legalOfficerAccountId: legalOfficer.account, description: "Identity LOC", draft: false, userIdentity: { @@ -85,8 +86,8 @@ async function createsIdentityLoc(state: State, account: ValidAccountId, legalOf const identityLocId = pendingRequest.data().id; // LLO Accepts - const lloClient = state.client.withCurrentAddress(legalOfficerAccount); - let lloLocs = await lloClient.locsState({ spec: { ownerAddress: legalOfficerAccount.address, locTypes: ["Identity"], statuses: ["REVIEW_PENDING"] } }); + const lloClient = state.client.withCurrentAccount(legalOfficer.account); + let lloLocs = await lloClient.locsState({ spec: { ownerAddress: legalOfficer.account.address, locTypes: ["Identity"], statuses: ["REVIEW_PENDING"] } }); const lloPending = lloLocs.findById(identityLocId) as PendingRequest; const lloAccepted = await lloPending.legalOfficer.accept(); diff --git a/packages/client-node/integration/Recovery.ts b/packages/client-node/integration/Recovery.ts index f7b5fc6d..9c170b63 100644 --- a/packages/client-node/integration/Recovery.ts +++ b/packages/client-node/integration/Recovery.ts @@ -16,16 +16,17 @@ import { } from "@logion/client"; import { IdentityLocs } from "./Protection.js"; import { aliceAcceptsTransfer } from "./Vault.js"; -import { initRequesterBalance, NEW_ADDRESS, REQUESTER_ADDRESS, State } from "./Utils.js"; +import { initAccountBalance, NEW_ADDRESS, REQUESTER_ADDRESS, State } from "./Utils.js"; +import debugLog = jasmine.debugLog; export async function requestRecoveryAndCancel(state: State, identityLocs: IdentityLocs) { - const { client, signer, alice, aliceAccount, charlie, charlieAccount } = state; + const { client, signer, alice, charlie, newAccount } = state; const pending = await requestRecovery(state, identityLocs) as PendingProtection; - console.log("LO's - Alice and Charlie Rejecting") - await rejectRequest(client, signer, charlie, charlieAccount, NEW_ADDRESS, "Your protection request is not complete"); - await rejectRequest(client, signer, alice, aliceAccount, NEW_ADDRESS, "Some info is missing"); + debugLog("LO's - Alice and Charlie Rejecting") + await rejectRequest(client, signer, charlie, newAccount, "Your protection request is not complete"); + await rejectRequest(client, signer, alice, newAccount, "Some info is missing"); const rejected = await pending.refresh() as RejectedRecovery; @@ -37,16 +38,15 @@ export async function rejectRequest( client: LogionClient, signer: FullSigner, legalOfficer: LegalOfficer, - legalOfficerAccount: ValidAccountId, - requesterAddress: string, + requester: ValidAccountId, reason: string, ) { - const axios = await buildLegalOfficerAxios(client, signer, legalOfficer, legalOfficerAccount); + const axios = await buildLegalOfficerAxios(client, signer, legalOfficer, legalOfficer.account); const response = await axios.put("/api/protection-request", { - legalOfficerAddress: legalOfficer.address, + legalOfficerAddress: legalOfficer.account.address, statuses: [ "PENDING" ], - requesterAddress + requesterAddress: requester.address, }); const request: ProtectionRequest = response.data.requests[0]; @@ -60,24 +60,22 @@ export async function acceptRequest( client: LogionClient, signer: FullSigner, legalOfficer: LegalOfficer, - legalOfficerAccount: ValidAccountId, - requesterAddress: string, + requester: ValidAccountId, ) { - const legalOfficerAddress = legalOfficer.address; - const axios = await buildLegalOfficerAxios(client, signer, legalOfficer, legalOfficerAccount); + const axios = await buildLegalOfficerAxios(client, signer, legalOfficer, legalOfficer.account); const response = await axios.put("/api/protection-request", { - legalOfficerAddress: legalOfficer.address, + legalOfficerAddress: legalOfficer.account.address, statuses: [ "PENDING" ], - requesterAddress + requesterAddress: requester.address, }); const request: ProtectionRequest = response.data.requests[0]; const identityLocId = await createAndCloseIdentityLoc( config, signer, - legalOfficerAddress, - request.requesterAddress + legalOfficer.account, + requester, ); await axios.post(`/api/protection-request/${ request.id }/accept`, { @@ -88,16 +86,16 @@ export async function acceptRequest( async function createAndCloseIdentityLoc( config: LogionClientConfig, signer: FullSigner, - legalOfficerAddress: string, - requesterAddress: string + legalOfficer: ValidAccountId, + requester: ValidAccountId ): Promise { const api = await buildApiClass(config.rpcEndpoints); const identityLocId = new UUID(); await signer.signAndSend({ - signerId: requesterAddress, + signerId: requester, submittable: api.polkadot.tx.logionLoc.createPolkadotIdentityLoc( api.adapters.toLocId(identityLocId), - legalOfficerAddress, + legalOfficer.address, api.fees.getDefaultLegalFee({ locType: "Identity" }).canonical, { metadata: [], @@ -107,7 +105,7 @@ async function createAndCloseIdentityLoc( ) }); await signer.signAndSend({ - signerId: legalOfficerAddress, + signerId: legalOfficer, submittable: api.polkadot.tx.logionLoc.close(api.adapters.toLocId(identityLocId), null, false) }); return identityLocId; @@ -126,27 +124,27 @@ async function buildLegalOfficerAxios( } export async function requestRecoveryWithResubmit(state: State, identityLocs: IdentityLocs) { - const { client, signer, alice, aliceAccount, charlie, charlieAccount } = state; + const { client, signer, alice, charlie, newAccount } = state; const requested = await requestRecovery(state, identityLocs); - console.log("LO's - Alice Rejecting") - await rejectRequest(client, signer, alice, aliceAccount, NEW_ADDRESS, "for some reason"); + debugLog("LO's - Alice Rejecting") + await rejectRequest(client, signer, alice, newAccount, "for some reason"); - console.log("User resubmitting to Alice"); + debugLog("User resubmitting to Alice"); const rejected = await requested.refresh() as RejectedRecovery; const pending = await rejected.resubmit(alice); - console.log("LO's - Accepting and vouching") - await acceptRequestAndVouch(client.config, client, signer, alice, aliceAccount, REQUESTER_ADDRESS, NEW_ADDRESS); - await acceptRequestAndVouch(client.config, client, signer, charlie, charlieAccount, REQUESTER_ADDRESS, NEW_ADDRESS); + debugLog("LO's - Accepting and vouching") + await acceptRequestAndVouch(client.config, client, signer, alice, REQUESTER_ADDRESS, newAccount); + await acceptRequestAndVouch(client.config, client, signer, charlie, REQUESTER_ADDRESS, newAccount); - console.log("Activating") + debugLog("Activating") const accepted = await pending.refresh() as AcceptedProtection; let pendingRecovery = await accepted.activate({ signer }) as PendingRecovery; pendingRecovery = await pendingRecovery.waitForFullyReady(); - console.log("Claiming") + debugLog("Claiming") await pendingRecovery.claimRecovery({ signer }); } @@ -155,24 +153,24 @@ export async function recoverLostVault(state: State) { const claimed = await getClaimedRecovery(state); - console.log("Transfer from recovered vault") + debugLog("Transfer from recovered vault") const newVault = await claimed.vaultState(); let recoveredVault = await claimed.recoveredVaultState(); recoveredVault = await recoveredVault.createVaultTransferRequest({ legalOfficer: alice, amount: Lgnt.fromCanonicalPrefixedNumber(recoveredVault.balances[0].available), - destination: newVault.vaultAddress, + destination: newVault.vaultAccount, signer, }); const pendingRequest = recoveredVault.pendingVaultTransferRequests[0]; - console.log("Alice accepts transfer from recovered vault") + debugLog("Alice accepts transfer from recovered vault") await aliceAcceptsTransfer(state, pendingRequest, claimed); } async function getClaimedRecovery(state: State) { const { client, newAccount } = state; - const authenticatedClient = client.withCurrentAddress(newAccount); + const authenticatedClient = client.withCurrentAccount(newAccount); const accepted = await authenticatedClient.protectionState() as ClaimedRecovery; expect(accepted).toBeInstanceOf(ClaimedRecovery); return accepted; @@ -183,7 +181,7 @@ export async function recoverLostAccount(state: State) { const claimed = await getClaimedRecovery(state); - console.log("Transfer from recovered account") + debugLog("Transfer from recovered account") const recoveredBalance = await claimed.recoveredBalanceState(); await recoveredBalance.transferAll({ signer, @@ -193,21 +191,21 @@ export async function recoverLostAccount(state: State) { } async function requestRecovery(state: State, identityLocs: IdentityLocs): Promise { - const { client, signer, alice, charlie, newAccount } = state; + const { client, signer, alice, charlie, newAccount, requesterAccount } = state; - await initRequesterBalance(client.config, signer, NEW_ADDRESS); + await initAccountBalance(state, newAccount); - const authenticatedClient = client.withCurrentAddress(newAccount); + const authenticatedClient = client.withCurrentAccount(newAccount); const current = await authenticatedClient.protectionState(); expect(current).toBeInstanceOf(NoProtection); if(current instanceof NoProtection) { - console.log("Requesting recovery") + debugLog("Requesting recovery") return await current.requestRecovery({ payload: { - recoveredAddress: REQUESTER_ADDRESS, - legalOfficer1: authenticatedClient.getLegalOfficer(alice.address), - legalOfficer2: authenticatedClient.getLegalOfficer(charlie.address), + recoveredAccount: requesterAccount, + legalOfficer1: authenticatedClient.getLegalOfficer(alice.account), + legalOfficer2: authenticatedClient.getLegalOfficer(charlie.account), requesterIdentityLoc1: identityLocs.alice, requesterIdentityLoc2: identityLocs.charlie, }, @@ -223,24 +221,23 @@ async function acceptRequestAndVouch( client: LogionClient, signer: FullSigner, legalOfficer: LegalOfficer, - legalOfficerAccount: ValidAccountId, lostAddress: string, - requesterAddress: string, + requesterAddress: ValidAccountId, ) { - await acceptRequest(config, client, signer, legalOfficer, legalOfficerAccount, requesterAddress) + await acceptRequest(config, client, signer, legalOfficer, requesterAddress) await vouchRecovery(config, signer, legalOfficer, lostAddress, requesterAddress) } async function vouchRecovery( config: LogionClientConfig, signer: FullSigner, - legalOfficerAddress: LegalOfficer, + legalOfficer: LegalOfficer, lost: string, - rescuer: string, + rescuer: ValidAccountId, ): Promise { const api = await buildApiClass(config.rpcEndpoints); await signer.signAndSend({ - signerId: legalOfficerAddress.address, - submittable: api.polkadot.tx.recovery.vouchRecovery(lost, rescuer) + signerId: legalOfficer.account, + submittable: api.polkadot.tx.recovery.vouchRecovery(lost, rescuer.address) }) } diff --git a/packages/client-node/integration/TokensRecord.ts b/packages/client-node/integration/TokensRecord.ts index afd9bd68..c24e0ace 100644 --- a/packages/client-node/integration/TokensRecord.ts +++ b/packages/client-node/integration/TokensRecord.ts @@ -7,16 +7,16 @@ import { PendingRequest, AcceptedRequest, OpenLoc, waitFor, BalanceState } from "@logion/client"; -import { initRequesterBalance, State, TEST_LOGION_CLIENT_CONFIG, ISSUER_ADDRESS } from "./Utils.js"; +import { initAccountBalance, State } from "./Utils.js"; import { NodeFile } from "../src/index.js"; export async function tokensRecords(state: State) { - const { client, alice, aliceAccount, newAccount, issuerAccount, signer } = state; + const { client, alice, newAccount, issuerAccount, signer } = state; - const userClient = state.client.withCurrentAddress(newAccount); + const userClient = state.client.withCurrentAccount(newAccount); const tokensRecordFee = Lgnt.fromCanonical(50n); let collectionLoc: LocRequestState = await (await userClient.locsState()).requestCollectionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "Some LOC with records", draft: false, valueFee: Lgnt.fromCanonical(100n), @@ -28,8 +28,8 @@ export async function tokensRecords(state: State) { } }); const collectionLocId = collectionLoc.locId; - const aliceClient = client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.address, locTypes: ["Collection"], statuses: ["REVIEW_PENDING"] } }); + const aliceClient = client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Collection"], statuses: ["REVIEW_PENDING"] } }); let alicePendingRequest = aliceLocs.findById(collectionLocId) as PendingRequest; let aliceAcceptedLoc = await alicePendingRequest.legalOfficer.accept(); @@ -37,12 +37,12 @@ export async function tokensRecords(state: State) { await acceptedLoc.open({ signer, autoPublish: false }); let aliceOpenLoc = await aliceAcceptedLoc.refresh() as OpenLoc; - aliceOpenLoc = await aliceOpenLoc.legalOfficer.selectIssuer({ issuer: ISSUER_ADDRESS, signer }); + aliceOpenLoc = await aliceOpenLoc.legalOfficer.selectIssuer({ issuer: issuerAccount, signer }); await aliceOpenLoc.legalOfficer.close({ signer, autoAck: false }); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, state.signer, ISSUER_ADDRESS); + await initAccountBalance(state, issuerAccount); - const issuerClient = state.client.withCurrentAddress(issuerAccount); + const issuerClient = state.client.withCurrentAccount(issuerAccount); let closedCollectionLoc = (await issuerClient.locsState()).findById(collectionLocId) as ClosedCollectionLoc; const recordId = Hash.of("record-id"); diff --git a/packages/client-node/integration/Utils.ts b/packages/client-node/integration/Utils.ts index 7c5b3be6..7002bd80 100644 --- a/packages/client-node/integration/Utils.ts +++ b/packages/client-node/integration/Utils.ts @@ -1,11 +1,10 @@ -import { buildApiClass, Lgnt, Numbers, ValidAccountId } from "@logion/node-api"; -import { Keyring } from "@polkadot/api"; +import { Lgnt, LogionNodeApiClass, ValidAccountId, AnyAccountId } from "@logion/node-api"; +import { Keyring, ApiPromise } from "@polkadot/api"; import { FullSigner, KeyringSigner, SignAndSendStrategy, - Signer, LogionClientConfig, ISubmittableResult, LogionClient, @@ -15,11 +14,11 @@ import { } from "@logion/client"; import { NodeAxiosFileUploader } from "../src/index.js"; -export const ALICE = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"; +export const ALICE = "vQx5kESPn8dWyX4KxMCKqUyCaWUwtui1isX6PVNcZh2Ghjitr"; export const ALICE_SECRET_SEED = "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"; -export const BOB = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"; +export const BOB = "vQvWaxNDdzuX5N3qSvGMtjdHcQdw1TAcPNgx4S1Utd3MTxYeN"; export const BOB_SECRET_SEED = "0x398f0c28f98885e046333d4a41c19cee4c37368a9832c6502f6cfd182e2aef89"; -export const CHARLIE = "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"; +export const CHARLIE = "vQvZF2YMgKuQhzfF7T3xDjHjuEmcPSUVEoUDPy1mzuSXzFgca"; export const CHARLIE_SECRET_SEED = "0xbc1ede780f784bb6991a585e4f6e61522c14e1cae6ad0895fb57b9a205a8f938"; class IntegrationTestSignAndSendStrategy implements SignAndSendStrategy { @@ -38,26 +37,26 @@ export function buildSigner(seeds: string []): FullSigner { export const TEST_LOGION_CLIENT_CONFIG: LogionClientConfig = { directoryEndpoint: "http://localhost:8090", - rpcEndpoints: [ 'ws://localhost:9944', 'ws://localhost:9945' ], + rpcEndpoints: [ 'ws://localhost:9944' ], buildFileUploader: () => new NodeAxiosFileUploader(), }; -export const REQUESTER_ADDRESS = "5DPLBrBxniGbGdFe1Lmdpkt6K3aNjhoNPJrSJ51rwcmhH2Tn"; +export const REQUESTER_ADDRESS = "vQtc8ViMVqMFymbKcCgV4VWaEkRKPQzXGtBFJb423qMn56cxf"; export const REQUESTER_SECRET_SEED = "unique chase zone team upset caution match west enter eyebrow limb wrist"; -export const DIRECT_REQUESTER_ADDRESS = "5EPPUZ9XEjeAgJj4DDtYn9thPtE68Nu7ZQDMySG3EP5nGVmV"; +export const DIRECT_REQUESTER_ADDRESS = "vQucBnRK4HNdZBGo2QZbySuaqqFy6ofd24GcEGRGE886A6Nta"; export const DIRECT_REQUESTER_SECRET_SEED = "pitch move leader grief stool crisp arm menu target hero inner essay"; -export const NEW_ADDRESS = "5FWP7ha7wBpRomanrgCFuV8c7gBTsyexzWZR42umqGv8Rpx4"; +export const NEW_ADDRESS = "vQvjBRZjeypopJjem41ugaEpkZ3vUZGNsVNxHM1uxj1vWFVa6"; export const NEW_SECRET_SEED = "inquiry nose frog devote demand main front caution excess bridge mom voice"; -export const ISSUER_ADDRESS = "5FU3mAsShn2b8CAe5cnVShzFNVgJssoXoMdAB9evGvKm5x4N"; +export const ISSUER_ADDRESS = "vQvgr532ykR1ydAEcGxVv7TgPosRKZAXSJE22U8f7AfL8uKUv"; export const ISSUER_SECRET_SEED = "exit photo know trouble stay hollow gate river upgrade twenty south random"; export const ETHEREUM_ADDRESS = "0x2469a2fd33ad71a3525cc2047bdd4f3ca851e89f"; export const ETHEREUM_SEED = "0x09dc05bbed08ff234919b84002a1eb6f856a6e949b017289fc7d457e1bb5e9d4"; -export const INVITED_CONTRIBUTOR_ADDRESS = "5F42HAi5kvD6Ao4Ze6UBiZDw7BA4zk62twNYRWAVDq3EhdWH"; +export const INVITED_CONTRIBUTOR_ADDRESS = "vQvGpb2scoZCUfm8XqSBcPJv5YYu5g2owPomQiVAg7a3cXGKJ"; export const INVITED_CONTRIBUTOR_SECRET_SEED = "october minimum future canvas range cruise jealous web renew border hover name"; export interface State { @@ -69,16 +68,14 @@ export interface State { requesterAccount: ValidAccountId, directRequesterAccount: ValidAccountId, newAccount: ValidAccountId, - aliceAccount: ValidAccountId, - bobAccount: ValidAccountId, - charlieAccount: ValidAccountId, issuerAccount: ValidAccountId, ethereumAccount: ValidAccountId, invitedContributorAccount: ValidAccountId, } -export async function setupInitialState(config: LogionClientConfig = TEST_LOGION_CLIENT_CONFIG): Promise { - const anonymousClient = await LogionClient.create(config); +export async function setupInitialState(config: LogionClientConfig = TEST_LOGION_CLIENT_CONFIG, mustUpdateLLOs = true): Promise { + let anonymousClient = await LogionClient.create(config); + const signer = buildSigner([ REQUESTER_SECRET_SEED, DIRECT_REQUESTER_SECRET_SEED, @@ -89,15 +86,28 @@ export async function setupInitialState(config: LogionClientConfig = TEST_LOGION ISSUER_SECRET_SEED, INVITED_CONTRIBUTOR_SECRET_SEED, ]); - const requesterAccount = anonymousClient.logionApi.queries.getValidAccountId(REQUESTER_ADDRESS, "Polkadot"); - const directRequesterAccount = anonymousClient.logionApi.queries.getValidAccountId(DIRECT_REQUESTER_ADDRESS, "Polkadot"); - const newAccount = anonymousClient.logionApi.queries.getValidAccountId(NEW_ADDRESS, "Polkadot"); - const aliceAccount = anonymousClient.logionApi.queries.getValidAccountId(ALICE, "Polkadot"); - const bobAccount = anonymousClient.logionApi.queries.getValidAccountId(BOB, "Polkadot"); - const charlieAccount = anonymousClient.logionApi.queries.getValidAccountId(CHARLIE, "Polkadot"); - const issuerAccount = anonymousClient.logionApi.queries.getValidAccountId(ISSUER_ADDRESS, "Polkadot"); - const ethereumAccount = anonymousClient.logionApi.queries.getValidAccountId(ETHEREUM_ADDRESS, "Ethereum"); - const invitedContributorAccount = anonymousClient.logionApi.queries.getValidAccountId(INVITED_CONTRIBUTOR_ADDRESS, "Polkadot"); + const requesterAccount = ValidAccountId.polkadot(REQUESTER_ADDRESS) + const directRequesterAccount = ValidAccountId.polkadot(DIRECT_REQUESTER_ADDRESS); + const newAccount = ValidAccountId.polkadot(NEW_ADDRESS); + const aliceAccount = ValidAccountId.polkadot(ALICE); + const bobAccount = ValidAccountId.polkadot(BOB); + const charlieAccount = ValidAccountId.polkadot(CHARLIE); + const issuerAccount = ValidAccountId.polkadot(ISSUER_ADDRESS); + const ethereumAccount = new AnyAccountId(ETHEREUM_ADDRESS, "Ethereum").toValidAccountId(); + const invitedContributorAccount = ValidAccountId.polkadot(INVITED_CONTRIBUTOR_ADDRESS); + + if (mustUpdateLLOs) { + await updateLegalOfficers({ + api: anonymousClient.logionApi.polkadot, + signer, + aliceAccount, + bobAccount, + charlieAccount + }); + } + + anonymousClient = await LogionClient.create(config); + const client = await anonymousClient.authenticate([ requesterAccount, directRequesterAccount, @@ -110,9 +120,12 @@ export async function setupInitialState(config: LogionClientConfig = TEST_LOGION invitedContributorAccount, ], signer); const legalOfficers = client.legalOfficers; - const alice = requireDefined(legalOfficers.find(legalOfficer => legalOfficer.address === ALICE)); - const bob = requireDefined(legalOfficers.find(legalOfficer => legalOfficer.address === BOB)); - const charlie = requireDefined(legalOfficers.find(legalOfficer => legalOfficer.address === CHARLIE)); + if (mustUpdateLLOs) { + console.log(legalOfficers.map(llo => `${ llo.name }:${ llo.account.address }`)) + } + const alice = requireDefined(legalOfficers.find(legalOfficer => legalOfficer.account.equals(aliceAccount))); + const bob = requireDefined(legalOfficers.find(legalOfficer => legalOfficer.account.equals(bobAccount))); + const charlie = requireDefined(legalOfficers.find(legalOfficer => legalOfficer.account.equals(charlieAccount))); return { client, signer, @@ -122,28 +135,71 @@ export async function setupInitialState(config: LogionClientConfig = TEST_LOGION requesterAccount, directRequesterAccount, newAccount, - aliceAccount, - bobAccount, - charlieAccount, issuerAccount, ethereumAccount, invitedContributorAccount, }; } +async function updateLegalOfficers(params: { api: ApiPromise, aliceAccount: ValidAccountId, bobAccount: ValidAccountId, charlieAccount: ValidAccountId, signer: FullSigner }): Promise { + const { api, aliceAccount, bobAccount, charlieAccount, signer } = params; + + const llo1 = signer.signAndSend({ + signerId: aliceAccount, + submittable: api.tx.loAuthorityList.updateLegalOfficer( + aliceAccount.address, + { + Host: { + nodeId: "0x0024080112201ce5f00ef6e89374afb625f1ae4c1546d31234e87e3c3f51a62b91dd6bfa57df", + baseUrl: "http://localhost:8080", + region: "Europe", + } + } + ), + }); + const llo2 = signer.signAndSend({ + signerId: bobAccount, + submittable: api.tx.loAuthorityList.updateLegalOfficer( + bobAccount.address, + { + Host: { + nodeId: "0x002408011220dacde7714d8551f674b8bb4b54239383c76a2b286fa436e93b2b7eb226bf4de7", + baseUrl: "http://localhost:8081", + region: "Europe", + } + } + ), + }); + const llo3 = signer.signAndSend({ + signerId: charlieAccount, + submittable: api.tx.loAuthorityList.updateLegalOfficer( + charlieAccount.address, + { + Host: { + nodeId: "0x002408011220876a7b4984f98006dc8d666e28b60de307309835d775e7755cc770328cdacf2e", + baseUrl: "http://localhost:8082", + region: "Europe", + } + } + ), + }); + await Promise.all([llo1, llo2, llo3]); +} + export async function updateConfig(config: Partial): Promise { const newConfig: LogionClientConfig = { ...TEST_LOGION_CLIENT_CONFIG, ...config, }; - return setupInitialState(newConfig); + return setupInitialState(newConfig, false); } -export async function initRequesterBalance(config: LogionClientConfig, signer: Signer, requester: string): Promise { - const api = await buildApiClass(config.rpcEndpoints); - const setBalance = api.polkadot.tx.balances.forceSetBalance(requester, Lgnt.from(10000).canonical); +export async function initAccountBalance(state: State, account: ValidAccountId): Promise { + const { alice, client, signer } = state + const api = await LogionNodeApiClass.connect(client.config.rpcEndpoints); + const setBalance = api.polkadot.tx.balances.forceSetBalance(account.address, Lgnt.from(10000).canonical); await signer.signAndSend({ - signerId: ALICE, + signerId: alice.account, submittable: api.polkadot.tx.sudo.sudo(setBalance), }); } @@ -153,11 +209,11 @@ export async function tearDown(state: State) { } export async function findWithLegalOfficerClient(client: LogionClient, loc: LocRequestState): Promise { - if(!client.currentAddress) { + if(!client.currentAccount) { throw new Error("Client must be authenticated"); } const locType = loc.data().locType; const locStatus = loc.data().status; - let aliceLocs = await client.locsState({ spec: { ownerAddress: client.currentAddress.address, locTypes: [locType], statuses: [locStatus] } }); + let aliceLocs = await client.locsState({ spec: { ownerAddress: client.currentAccount.address, locTypes: [locType], statuses: [locStatus] } }); return aliceLocs.findById(loc.locId); } diff --git a/packages/client-node/integration/Vault.ts b/packages/client-node/integration/Vault.ts index a54e618c..b306ef09 100644 --- a/packages/client-node/integration/Vault.ts +++ b/packages/client-node/integration/Vault.ts @@ -1,23 +1,23 @@ -import { buildApiClass, Lgnt } from "@logion/node-api"; +import { LogionNodeApiClass, Lgnt, ValidAccountId } from "@logion/node-api"; import { ActiveProtection, VaultTransferRequest, WithProtectionParameters } from "@logion/client"; -import { REQUESTER_ADDRESS, State } from "./Utils.js"; +import { State } from "./Utils.js"; import { checkCoinBalance } from "./Balance.js"; export async function providesVault(state: State) { const { client, signer, alice, requesterAccount } = state; - const userClient = client.withCurrentAddress(requesterAccount); + const userClient = client.withCurrentAccount(requesterAccount); let activeProtection = (await userClient.protectionState()) as ActiveProtection; activeProtection = await activeProtection.waitForFullyReady(); // Transfer to vault let vaultState = await activeProtection.vaultState(); - const vaultAddress = vaultState.vaultAddress; + const vaultAccount = vaultState.vaultAccount; let balanceState = await userClient.balanceState(); balanceState = await balanceState.transfer({ signer, - destination: vaultAddress, + destination: vaultAccount, amount: Lgnt.from(5n), }); vaultState = await vaultState.refresh(); @@ -27,7 +27,7 @@ export async function providesVault(state: State) { vaultState = await vaultState.createVaultTransferRequest({ legalOfficer: alice, amount: Lgnt.from(1n), - destination: REQUESTER_ADDRESS, + destination: requesterAccount, signer }); const pendingRequest = vaultState.pendingVaultTransferRequests[0]; @@ -43,19 +43,19 @@ export async function providesVault(state: State) { } export async function aliceAcceptsTransfer(state: State, request: VaultTransferRequest, activeProtection: WithProtectionParameters) { - const { client, signer, aliceAccount, requesterAccount } = state; + const { client, signer, alice, requesterAccount } = state; - const api = await buildApiClass(client.config.rpcEndpoints); + const api = await LogionNodeApiClass.connect(client.config.rpcEndpoints); - const signerId = aliceAccount.address; + const signerId = alice.account; const amount = Lgnt.fromCanonical(BigInt(request!.amount)); const vault = api.vault( - requesterAccount.address, - activeProtection.protectionParameters.legalOfficers.map(legalOfficer => legalOfficer.address), + requesterAccount, + activeProtection.protectionParameters.legalOfficers.map(legalOfficer => legalOfficer.account), ); const submittable = await vault.tx.approveVaultTransfer({ signerId, - destination: request!.destination, + destination: ValidAccountId.polkadot(request!.destination), amount, block: BigInt(request!.block), index: request!.index, @@ -65,7 +65,7 @@ export async function aliceAcceptsTransfer(state: State, request: VaultTransferR submittable, }); - const authenticated = client.withCurrentAddress(aliceAccount); - const axios = authenticated.getLegalOfficer(aliceAccount.address).buildAxiosToNode(); + const authenticated = client.withCurrentAccount(alice.account); + const axios = authenticated.getLegalOfficer(alice.account).buildAxiosToNode(); await axios.post(`/api/vault-transfer-request/${request.id}/accept`); } diff --git a/packages/client-node/integration/VerifiedIssuer.ts b/packages/client-node/integration/VerifiedIssuer.ts index 2c628baf..da5cdf3b 100644 --- a/packages/client-node/integration/VerifiedIssuer.ts +++ b/packages/client-node/integration/VerifiedIssuer.ts @@ -5,18 +5,18 @@ import { AcceptedRequest, PendingRequest, OpenLoc, MimeType, waitFor } from "@logion/client"; -import { State, ISSUER_ADDRESS, initRequesterBalance, TEST_LOGION_CLIENT_CONFIG } from "./Utils.js"; +import { State, initAccountBalance } from "./Utils.js"; import { NodeFile } from "../src/index.js"; export async function verifiedIssuer(state: State) { - const { alice, aliceAccount, issuerAccount, newAccount, signer } = state; + const { alice, issuerAccount, newAccount, signer } = state; - const issuerClient = state.client.withCurrentAddress(issuerAccount); + const issuerClient = state.client.withCurrentAccount(issuerAccount); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, signer, ISSUER_ADDRESS); + await initAccountBalance(state, issuerAccount); let issuerLocsState = await issuerClient.locsState(); const pendingRequest = await issuerLocsState.requestIdentityLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "This is a verified issuer Identity LOC", userIdentity: { email: "john.doe.trusted@invalid.domain", @@ -35,8 +35,8 @@ export async function verifiedIssuer(state: State) { }); const issuerIdentityLocId = pendingRequest.data().id; - const aliceClient = state.client.withCurrentAddress(aliceAccount); - let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: aliceAccount.address, locTypes: ["Identity"], statuses: ["REVIEW_PENDING"] } }); + const aliceClient = state.client.withCurrentAccount(alice.account); + let aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Identity"], statuses: ["REVIEW_PENDING"] } }); const alicePending = aliceLocs.findById(issuerIdentityLocId) as PendingRequest; const aliceAccepted = await alicePending.legalOfficer.accept(); @@ -51,17 +51,17 @@ export async function verifiedIssuer(state: State) { let aliceClosed = await aliceOpen.legalOfficer.close({ signer, autoAck: false }) as ClosedLoc; aliceClosed = await aliceClosed.legalOfficer.nominateIssuer({ signer }); - await initRequesterBalance(TEST_LOGION_CLIENT_CONFIG, signer, newAccount.address); - const requesterClient = state.client.withCurrentAddress(newAccount); + await initAccountBalance(state, newAccount); + const requesterClient = state.client.withCurrentAccount(newAccount); let userLocsState = await requesterClient.locsState(); let pendingLocRequest = await userLocsState.requestTransactionLoc({ - legalOfficerAddress: alice.address, + legalOfficerAccountId: alice.account, description: "Some LOC with verified issuer", draft: false, }) as PendingRequest; const transactionLocId = pendingLocRequest.data().id; - aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: aliceAccount.address, locTypes: ["Transaction"], statuses: ["REVIEW_PENDING"] } }); + aliceLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Transaction"], statuses: ["REVIEW_PENDING"] } }); const alicePendingTransaction = aliceLocs.findById(transactionLocId) as PendingRequest; const aliceAcceptedTransaction = await alicePendingTransaction.legalOfficer.accept() as AcceptedRequest; @@ -70,7 +70,7 @@ export async function verifiedIssuer(state: State) { let aliceOpenTransaction = await aliceAcceptedTransaction.refresh() as OpenLoc; aliceOpenTransaction = await aliceOpenTransaction.legalOfficer.selectIssuer({ - issuer: ISSUER_ADDRESS, + issuer: issuerAccount, signer, }); openLoc = await openLoc.refresh() as OpenLoc; @@ -122,7 +122,7 @@ export async function verifiedIssuer(state: State) { // Issuer unselection aliceOpenTransaction = await aliceOpenTransaction.refresh() as OpenLoc; aliceOpenTransaction = await aliceOpenTransaction.legalOfficer.unselectIssuer({ - issuer: ISSUER_ADDRESS, + issuer: issuerAccount, signer }); diff --git a/packages/client-node/integration/Void.ts b/packages/client-node/integration/Void.ts index f5f73f7b..fe70199f 100644 --- a/packages/client-node/integration/Void.ts +++ b/packages/client-node/integration/Void.ts @@ -2,9 +2,9 @@ import { VoidedLoc } from "@logion/client"; import { State } from "./Utils.js"; export async function voidTransactionLoc(state: State) { - const { aliceAccount, signer } = state; - const client = state.client.withCurrentAddress(aliceAccount); - let locsState = await client.locsState({ spec: { ownerAddress: aliceAccount.address, locTypes: ["Transaction"], statuses: ["CLOSED"] }}); + const { alice, signer } = state; + const client = state.client.withCurrentAccount(alice.account); + let locsState = await client.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Transaction"], statuses: ["CLOSED"] }}); const closedLoc = locsState.closedLocs['Transaction'][0]; const voidLoc = await closedLoc.legalOfficer.voidLoc({ diff --git a/packages/client-node/integration/Vote.ts b/packages/client-node/integration/Vote.ts index 5a5041f6..06a26bed 100644 --- a/packages/client-node/integration/Vote.ts +++ b/packages/client-node/integration/Vote.ts @@ -2,11 +2,11 @@ import { ClosedLoc, PendingVote, Votes, waitFor } from "@logion/client"; import { State } from "./Utils.js"; export async function votingProcess(state: State) { - const { client, alice, aliceAccount, bobAccount, charlieAccount, signer } = state; + const { client, alice, bob, charlie, signer } = state; - const aliceClient = client.withCurrentAddress(aliceAccount); - const closedIdentityLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.address, locTypes: ["Identity"], statuses: ["CLOSED"] } }); - const votableLoc = closedIdentityLocs.closedLocs["Identity"].find(loc => loc.data().requesterAddress !== undefined && loc.data().requesterAddress?.type === "Polkadot") as ClosedLoc; + const aliceClient = client.withCurrentAccount(alice.account); + const closedIdentityLocs = await aliceClient.locsState({ spec: { ownerAddress: alice.account.address, locTypes: ["Identity"], statuses: ["CLOSED"] } }); + const votableLoc = closedIdentityLocs.closedLocs["Identity"].find(loc => loc.data().requesterAccountId !== undefined && loc.data().requesterAccountId?.type === "Polkadot") as ClosedLoc; await votableLoc.legalOfficer.requestVote({ signer }); @@ -18,14 +18,14 @@ export async function votingProcess(state: State) { let pendingVote = votes.votes[0] as PendingVote; pendingVote = await pendingVote.castVote({ result: "Yes", signer }); - const bobClient = client.withCurrentAddress(bobAccount); + const bobClient = client.withCurrentAccount(bob.account); const bobVotes = await bobClient.voter.getVotes(); let bobPendingVote = bobVotes.votes[0] as PendingVote; const bobLoc = bobClient.voter.findLocById(bobPendingVote.data.locId); expect(bobLoc).toBeDefined(); bobPendingVote = await bobPendingVote.castVote({ result: "No", signer }); - const charlieClient = client.withCurrentAddress(charlieAccount); + const charlieClient = client.withCurrentAccount(charlie.account); const charlieVotes = await charlieClient.voter.getVotes(); let charliePendingVote = charlieVotes.votes[0] as PendingVote; await charliePendingVote.castVote({ result: "No", signer }); diff --git a/packages/client-node/package.json b/packages/client-node/package.json index 9885912a..5ba39faf 100644 --- a/packages/client-node/package.json +++ b/packages/client-node/package.json @@ -7,7 +7,7 @@ "type": "module", "scripts": { "build": "yarn lint && tsc -p tsconfig.json", - "integration-test": "docker compose up -d && node ./scripts/init_onchain_data.js && ./scripts/integration_test_db_setup.sh && NODE_OPTIONS=--loader=ts-node/esm jasmine --config=jasmine-integration.json ; docker compose down", + "integration-test": "docker compose up -d && ./scripts/integration_test_db_setup.sh && NODE_OPTIONS=--loader=ts-node/esm jasmine --config=jasmine-integration.json ; docker compose down", "lint": "yarn eslint src/**", "test": "NODE_OPTIONS=--loader=ts-node/esm jasmine --config=jasmine.json", "clean": "rm -rf dist" diff --git a/packages/client-node/scripts/init_onchain_data.js b/packages/client-node/scripts/init_onchain_data.js deleted file mode 100644 index 744ad5c7..00000000 --- a/packages/client-node/scripts/init_onchain_data.js +++ /dev/null @@ -1,58 +0,0 @@ -import { buildApiClass } from "@logion/node-api"; -import { Keyring } from '@polkadot/api'; - -let api; -let keyring; -let alice; -let bob; -let charlie; - -buildApiClass("ws://localhost:9944") -.then(api0 => { - api = api0.polkadot; - keyring = new Keyring({ type: 'sr25519' }); - alice = keyring.addFromUri("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"); - bob = keyring.addFromUri("0x398f0c28f98885e046333d4a41c19cee4c37368a9832c6502f6cfd182e2aef89"); - charlie = keyring.addFromUri("0xbc1ede780f784bb6991a585e4f6e61522c14e1cae6ad0895fb57b9a205a8f938"); - - return api.tx.loAuthorityList - .updateLegalOfficer(alice.address, { - Host: { - nodeId: "0x0024080112201ce5f00ef6e89374afb625f1ae4c1546d31234e87e3c3f51a62b91dd6bfa57df", - baseUrl: "http://localhost:8080", - region: "Europe", - } - }) - .signAndSend(alice); -}) -.then(hash => { - console.log(`Alice update tx hash: ${hash}`); - return api.tx.loAuthorityList - .updateLegalOfficer(bob.address, { - Host: { - nodeId: "0x002408011220dacde7714d8551f674b8bb4b54239383c76a2b286fa436e93b2b7eb226bf4de7", - baseUrl: "http://localhost:8081", - region: "Europe", - } - }) - .signAndSend(bob); -}) -.then(hash => { - console.log(`Bob update tx hash: ${hash}`); - return api.tx.loAuthorityList - .updateLegalOfficer(charlie.address, { - Host: { - nodeId: "0x002408011220876a7b4984f98006dc8d666e28b60de307309835d775e7755cc770328cdacf2e", - baseUrl: "http://localhost:8082", - region: "Europe", - } - }) - .signAndSend(charlie); -}) -.then(hash => { - console.log(`Charlie update tx hash: ${hash}`); - return api.disconnect(); -}) -.then(() => { - console.log("Done"); -}); diff --git a/packages/client/src/Polling.ts b/packages/client/src/Polling.ts index 8bd56e61..9bca7e79 100644 --- a/packages/client/src/Polling.ts +++ b/packages/client/src/Polling.ts @@ -13,7 +13,7 @@ export interface WaitForParameters { export const DEFAULT_POLLING_PARAMETERS: PollingParameters = { period: Duration.fromMillis(1000), - maxRetries: 20, + maxRetries: 40, }; export function waitFor(params: WaitForParameters): Promise {