diff --git a/docs-main/docs.json b/docs-main/docs.json index 2689f9cef..e958500e8 100644 --- a/docs-main/docs.json +++ b/docs-main/docs.json @@ -65,9 +65,7 @@ }, { "group": "Core Concepts", - "pages": [ - "overview/understand/core-concepts" - ] + "pages": ["overview/understand/core-concepts"] }, { "group": "Global Synchronizer", @@ -303,9 +301,7 @@ }, { "group": "App Rewards", - "pages": [ - "appdev/app-rewards" - ] + "pages": ["appdev/app-rewards"] }, { "group": "Troubleshooting", @@ -728,9 +724,7 @@ "groups": [ { "group": "Overview", - "pages": [ - "sdks-tools/overview" - ] + "pages": ["sdks-tools/overview"] }, { "group": "SDKs", @@ -745,7 +739,6 @@ "group": "Using the SDK", "pages": [ "sdks-tools/sdks/wallet-sdk/using-the-sdk/configuration", - "sdks-tools/sdks/wallet-sdk/using-the-sdk/user-management", "sdks-tools/sdks/wallet-sdk/using-the-sdk/registering-plugins", { "group": "v0 to v1 migration", @@ -770,7 +763,8 @@ "sdks-tools/sdks/wallet-sdk/guides/preparing-and-signing-a-transaction", "sdks-tools/sdks/wallet-sdk/guides/transfer-types", "sdks-tools/sdks/wallet-sdk/guides/performing-a-cc-tap", - "sdks-tools/sdks/wallet-sdk/guides/signing-transactions-from-third-party-dapps" + "sdks-tools/sdks/wallet-sdk/guides/signing-transactions-from-third-party-dapps", + "sdks-tools/sdks/wallet-sdk/guides/user-management" ] }, "integrations/release-notes/wallet-sdk" @@ -2178,9 +2172,7 @@ "source": "openapi/splice/scan/scan-stream-server.yaml", "directory": "reference/splice-scan-streaming-api" }, - "pages": [ - "GET /v0/history/bulk/download/{object_key}" - ] + "pages": ["GET /v0/history/bulk/download/{object_key}"] } ] }, @@ -2207,10 +2199,7 @@ "source": "openapi/splice/validator/ans-external.yaml", "directory": "reference/splice-ans-api" }, - "pages": [ - "POST /v0/entry/create", - "GET /v0/entry/all" - ] + "pages": ["POST /v0/entry/create", "GET /v0/entry/all"] }, { "group": "Scan Proxy API", @@ -2845,9 +2834,7 @@ "product": "Version Dashboard", "icon": "table", "root": "shared/version-compatibility-dashboard", - "pages": [ - "shared/version-compatibility-dashboard" - ] + "pages": ["shared/version-compatibility-dashboard"] } ] }, diff --git a/docs-main/sdks-tools/sdks/wallet-sdk/guides/user-management.mdx b/docs-main/sdks-tools/sdks/wallet-sdk/guides/user-management.mdx new file mode 100644 index 000000000..b0810a2d4 --- /dev/null +++ b/docs-main/sdks-tools/sdks/wallet-sdk/guides/user-management.mdx @@ -0,0 +1,202 @@ +--- +title: "User Management" +description: "Create users and configure ledger read/act rights, including canReadAsAnyParty and canExecuteAsAnyParty." +--- + +The Wallet SDK has functionality for creating and managing user rights, by default when you are connecting it uses whichever user is defined in your token provider config. If the user is an admin user on the ledger api they can be used to create other users and grant them rights. + +## How do I quickly setup canReadAsAnyParty and canExecuteAsAnyParty? + +This script sets up three users `alice`, `bob` and `master`. `master` is given canReadAsAnyParty and canExecuteAsAnyParty and it shows proper access control by creating parties and ensuring that `alice` and `bob` can not see each others parties. + +```typescript +import { localNetStaticConfig, SDK } from "@canton-network/wallet-sdk"; +import { pino } from "pino"; +import { TOKEN_PROVIDER_CONFIG_DEFAULT } from "./utils/index.js"; +const logger = pino({ name: "v1-multi-user-setup", level: "info" }); + +logger.info("Operator sets up users and primary parties"); + +const operatorSdk = await SDK.create({ + auth: TOKEN_PROVIDER_CONFIG_DEFAULT, + ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, +}); + +const aliceInternal = await operatorSdk.party.internal.allocate({ + partyHint: "v1-09-alice", +}); + +const bobInternal = await operatorSdk.party.internal.allocate({ + partyHint: "v1-09-bob", +}); + +const masterPartyInternal = await operatorSdk.party.internal.allocate({ + partyHint: "v1-09-master", +}); + +logger.info("Created the internal parties"); + +const aliceUser = await operatorSdk.user.create({ + userId: "alice-user", + primaryParty: aliceInternal, + userRights: { + participantAdmin: true, + }, +}); + +const bobUser = await operatorSdk.user.create({ + userId: "bob-user", + primaryParty: bobInternal, + userRights: { + participantAdmin: true, + }, +}); + +const masterUser = await operatorSdk.user.create({ + userId: "master-user", + primaryParty: masterPartyInternal, + userRights: { + participantAdmin: true, + }, +}); + +logger.info("created the users"); + +if (!(aliceUser || bobUser || masterUser)) { + throw new Error(`One of the users was not created correctly`); +} + +await operatorSdk.user.rights.grant({ + userId: masterUser.id!, + userRights: { + canExecuteAsAnyParty: true, + canReadAsAnyParty: true, + }, +}); + +logger.info( + `Created alice user: ${aliceUser.id} with primary party (internal) ${aliceUser.primaryParty}`, +); +logger.info( + `Created bob user: ${bobUser.id} with primary party (internal) ${bobUser.primaryParty}`, +); +logger.info( + `Created master user: ${masterUser.id} with primary party (internal) ${masterUser.primaryParty}, with read as and execute as rights`, +); + +const aliceSdk = await SDK.create({ + auth: { + method: "self_signed", + issuer: "unsafe-auth", + credentials: { + clientId: aliceUser.id, + clientSecret: "unsafe", + audience: "https://canton.network.global", + scope: "", + }, + }, + ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, +}); + +const aliceKeyPair = aliceSdk.keys.generate(); +const aliceExternal = await aliceSdk.party.external + .create(aliceKeyPair.publicKey, { + partyHint: "v1-09-alice", + }) + .sign(aliceKeyPair.privateKey) + .execute(); + +logger.info(`alice created external party`); + +const bobSdk = await SDK.create({ + auth: { + method: "self_signed", + issuer: "unsafe-auth", + credentials: { + clientId: bobUser.id, + clientSecret: "unsafe", + audience: "https://canton.network.global", + scope: "", + }, + }, + ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, +}); + +const bobKeyPair = bobSdk.keys.generate(); +const bobExternal = await bobSdk.party.external + .create(bobKeyPair.publicKey, { + partyHint: "v1-09-bob", + }) + .sign(bobKeyPair.privateKey) + .execute(); +logger.info(`bob created external party`); + +const masterUserSdk = await SDK.create({ + auth: { + method: "self_signed", + issuer: "unsafe-auth", + credentials: { + clientId: masterUser.id, + clientSecret: "unsafe", + audience: "https://canton.network.global", + scope: "", + }, + }, + ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, +}); + +const masterWalletView = await masterUserSdk.party.list(); + +if (!masterWalletView?.find((p) => p === aliceExternal.partyId)) { + throw new Error("master user cannot see alice party"); +} +if (!masterWalletView?.find((p) => p === bobExternal.partyId)) { + throw new Error("master user cannot see bob party"); +} + +const aliceWalletView = await aliceSdk.party.list(); +logger.info(aliceWalletView); + +if (aliceWalletView?.find((p) => p === bobExternal.partyId)) { + throw new Error("alice user can see bob party"); +} + +const bobWalletView = await bobSdk.party.list(); + +if (bobWalletView?.find((p) => p === aliceExternal.partyId)) { + throw new Error("bob user can see alice party"); +} + +logger.info( + "alice and bob have proper isolation and cannot see each others external parties", +); + +//user management test +await bobSdk.user.rights.grant({ + userRights: { + readAs: [aliceExternal.partyId], + }, +}); + +const bobWalletViewAfterGrantRights = await bobSdk.party.list(); + +if (!bobWalletViewAfterGrantRights?.find((p) => p === aliceExternal.partyId)) { + throw new Error("bob user cannot see alice party even with ReadAs rights"); +} + +const bobRightsAfterGrantRights = await bobSdk.user.rights.list(); + +logger.info(bobRightsAfterGrantRights, "Bob user rights"); + +await bobSdk.user.rights.revoke({ + userRights: { + readAs: [aliceExternal.partyId], + }, +}); + +const bobWalletViewAfterRevokeRights = await bobSdk.party.list(); + +if (bobWalletViewAfterRevokeRights?.find((p) => p === aliceExternal.partyId)) { + throw new Error("bob user can see alice party even after revoking rights"); +} +``` diff --git a/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/configuration.mdx b/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/configuration.mdx index aab51b51b..f0274d5c0 100644 --- a/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/configuration.mdx +++ b/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/configuration.mdx @@ -248,10 +248,8 @@ Each non-LocalNet environment requires different connection endpoints. Configure - **JSON Ledger API URL** — The HTTP/JSON API endpoint for your validator's participant - **gRPC Admin API URL** — The gRPC endpoint for participant administration -- **Validator API URL** — The validator app's REST API endpoint - **Scan API URL** — The Scan service endpoint (either direct or via the BFT scan proxy) - **Auth token** — A valid JWT token from your OIDC provider - - +- **Validator API URL** — The validator app's REST API endpoint (optional for token/amulet namespaces, if not provided will use the scan api) See the [config template](https://github.com/canton-network/wallet-gateway/blob/main/docs/wallet-integration-guide/examples/snippets/config-template.ts) in the Wallet SDK repository for a complete example. diff --git a/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/user-management.mdx b/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/user-management.mdx deleted file mode 100644 index 9db3a62da..000000000 --- a/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/user-management.mdx +++ /dev/null @@ -1,296 +0,0 @@ ---- -title: 'User Management' -description: 'Create users and configure ledger read/act rights, including canReadAsAnyParty and canExecuteAsAnyParty.' ---- - -The Wallet SDK has functionality for creating and managing user rights, by default when you are connecting it uses whichever user is defined in your auth-controller. If the user is an admin user on the ledger api they can be used to create other users and grant them rights. - -## How do I quickly setup canReadAsAnyParty and canExecuteAsAnyParty? - -This script sets up three users `alice`, `bob` and `master`. `master` is given canReadAsAnyParty and canExecuteAsAnyParty and it shows proper access control by creating parties and ensuring that `alice` and `bob` can not see each others parties. - -``` typescript -import { localNetStaticConfig, SDK } from '@canton-network/wallet-sdk' -import { pino } from 'pino' -import { TOKEN_PROVIDER_CONFIG_DEFAULT } from './utils/index.js' -const logger = pino({ name: 'v1-multi-user-setup', level: 'info' }) - -logger.info('Operator sets up users and primary parties') - -const operatorSdk = await SDK.create({ - auth: TOKEN_PROVIDER_CONFIG_DEFAULT, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, -}) - -const aliceInternal = await operatorSdk.party.internal.allocate({ - partyHint: 'v1-09-alice', -}) - -const bobInternal = await operatorSdk.party.internal.allocate({ - partyHint: 'v1-09-bob', -}) - -const masterPartyInternal = await operatorSdk.party.internal.allocate({ - partyHint: 'v1-09-master', -}) - -logger.info('Created the internal parties') - -const aliceUser = await operatorSdk.user.create({ - userId: 'alice-user', - primaryParty: aliceInternal, - userRights: { - participantAdmin: true, - }, -}) - -const bobUser = await operatorSdk.user.create({ - userId: 'bob-user', - primaryParty: bobInternal, - userRights: { - participantAdmin: true, - }, -}) - -const masterUser = await operatorSdk.user.create({ - userId: 'master-user', - primaryParty: masterPartyInternal, - userRights: { - participantAdmin: true, - }, -}) - -logger.info('created the users') - -if (!(aliceUser || bobUser || masterUser)) { - throw new Error(`One of the users was not created correctly`) -} - -await operatorSdk.user.rights.grant({ - userId: masterUser.id!, - userRights: { - canExecuteAsAnyParty: true, - canReadAsAnyParty: true, - }, -}) - -logger.info( - `Created alice user: ${aliceUser.id} with primary party (internal) ${aliceUser.primaryParty}` -) -logger.info( - `Created bob user: ${bobUser.id} with primary party (internal) ${bobUser.primaryParty}` -) -logger.info( - `Created master user: ${masterUser.id} with primary party (internal) ${masterUser.primaryParty}, with read as and execute as rights` -) - -const aliceSdk = await SDK.create({ - auth: { - method: 'self_signed', - issuer: 'unsafe-auth', - credentials: { - clientId: aliceUser.id, - clientSecret: 'unsafe', - audience: 'https://canton.network.global', - scope: '', - }, - }, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, -}) - -const aliceKeyPair = aliceSdk.keys.generate() -const aliceExternal = await aliceSdk.party.external - .create(aliceKeyPair.publicKey, { - partyHint: 'v1-09-alice', - }) - .sign(aliceKeyPair.privateKey) - .execute() - -logger.info(`alice created external party`) - -const bobSdk = await SDK.create({ - auth: { - method: 'self_signed', - issuer: 'unsafe-auth', - credentials: { - clientId: bobUser.id, - clientSecret: 'unsafe', - audience: 'https://canton.network.global', - scope: '', - }, - }, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, -}) - -const bobKeyPair = bobSdk.keys.generate() -const bobExternal = await bobSdk.party.external - .create(bobKeyPair.publicKey, { - partyHint: 'v1-09-bob', - }) - .sign(bobKeyPair.privateKey) - .execute() -logger.info(`bob created external party`) - -const masterUserSdk = await SDK.create({ - auth: { - method: 'self_signed', - issuer: 'unsafe-auth', - credentials: { - clientId: masterUser.id, - clientSecret: 'unsafe', - audience: 'https://canton.network.global', - scope: '', - }, - }, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, -}) - -const masterWalletView = await masterUserSdk.party.list() - -if (!masterWalletView?.find((p) => p === aliceExternal.partyId)) { - throw new Error('master user cannot see alice party') -} -if (!masterWalletView?.find((p) => p === bobExternal.partyId)) { - throw new Error('master user cannot see bob party') -} - -const aliceWalletView = await aliceSdk.party.list() -logger.info(aliceWalletView) - -if (aliceWalletView?.find((p) => p === bobExternal.partyId)) { - throw new Error('alice user can see bob party') -} - -const bobWalletView = await bobSdk.party.list() - -if (bobWalletView?.find((p) => p === aliceExternal.partyId)) { - throw new Error('bob user can see alice party') -} - -logger.info( - 'alice and bob have proper isolation and cannot see each others external parties' -) - -//user management test -await bobSdk.user.rights.grant({ - userRights: { - readAs: [aliceExternal.partyId], - }, -}) - -const bobWalletViewAfterGrantRights = await bobSdk.party.list() - -if (!bobWalletViewAfterGrantRights?.find((p) => p === aliceExternal.partyId)) { - throw new Error('bob user cannot see alice party even with ReadAs rights') -} - -const bobRightsAfterGrantRights = await bobSdk.user.rights.list() - -logger.info(bobRightsAfterGrantRights, 'Bob user rights') - -await bobSdk.user.rights.revoke({ - userRights: { - readAs: [aliceExternal.partyId], - }, -}) - -const bobWalletViewAfterRevokeRights = await bobSdk.party.list() - -if (bobWalletViewAfterRevokeRights?.find((p) => p === aliceExternal.partyId)) { - throw new Error('bob user can see alice party even after revoking rights') -} -``` - -## Creating a new user - -Creating a new user can be done using the adminLedger, this new user can then be granted rights or can create new parties as needed. - -``` typescript -import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk' - -export default async function () { - // it is important to configure the SDK correctly else you might run into connectivity or authentication issues - const sdk = await SDK.create({ - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, - }) - - await sdk.user.create({ - userId: 'alice-user', - primaryParty: global.EXISTING_PARTY_1, - }) -} -``` - -## ReadAs and ActAs limitations - -Currently when allocating a new party we also grant ReadAs and ActAs rights for that party for the submitting user. This allows the user to do the normal flows involved like preparing transactions and executing those. There are performance issues if too many of these rights are assigned to the same user, in the case of a `master` user that is interacting on behalf of a client, then it might be more convenient to use `CanReadAsAnyParty` and `CanExecuteAsAnyParty` as described below. - -Here is how the method changes if you need to allocate a party without granting rights: - -``` typescript -import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk' - -export default async function () { - // it is important to configure the SDK correctly else you might run into connectivity or authentication issues - const sdk = await SDK.create({ - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, - }) - const key = sdk.keys.generate() - - const party = await sdk.party.external - .create(key.publicKey, { partyHint: 'my-party-without-rights' }) - .sign(key.privateKey) - .execute({ grantUserRights: false }) //do not grant user actAs and readAs for the party -} -``` - -## CanReadAsAnyParty - -CanReadAsAnyParty gives a user full information about any party on the ledger, if a user is set up with this they will see: 1. All parties hosted on the ledger (multi-hosted and single hosted) 2. All transaction happening involving a party on the ledger 3. Prepare transactions on behalf of any party - -This will not grant information about parties hosted on other ledgers or their transactions. - -``` typescript -import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk' - -export default async function () { - // it is important to configure the SDK correctly else you might run into connectivity or authentication issues - const sdk = await SDK.create({ - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, - }) - - await sdk.user.rights.grant({ - userRights: { canReadAsAnyParty: true }, - }) -} -``` - -The SDK automatically leverages this elevated permission for certain endpoints like `listWallets`. - -## CanExecuteAsAnyParty - -CanExecuteAsAnyParty gives full execution rights for a party, this means that a user with these rights can submit transaction on behalf of a party hosted on the ledger. - -**This does not give the user rights to move funds without a valid signature!** - -The setup is similar to the \`CanReadAsAnyParty\`: - -``` typescript -import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk' - -export default async function () { - // it is important to configure the SDK correctly else you might run into connectivity or authentication issues - const sdk = await SDK.create({ - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL, - }) - - //optional arguments are idp and userId; if not provided, will use the default idp and extract the userId from the auth token - await sdk.user.rights.grant({ - userRights: { canExecuteAsAnyParty: true }, - }) -} -``` \ No newline at end of file diff --git a/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/v0-to-v1-migration.mdx b/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/v0-to-v1-migration.mdx index 43ac8bc0a..5c565022c 100644 --- a/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/v0-to-v1-migration.mdx +++ b/docs-main/sdks-tools/sdks/wallet-sdk/using-the-sdk/v0-to-v1-migration.mdx @@ -1,6 +1,6 @@ --- -title: 'SDK v0 to v1 Migration Guide' -description: 'Migrate the Wallet SDK from v0 to v1.' +title: "SDK v0 to v1 Migration Guide" +description: "Migrate the Wallet SDK from v0 to v1." --- Wallet SDK v1 is not backwards compatible with v0. @@ -15,99 +15,97 @@ We have removed the configure() and connect() pattern in favor of passing in a s Static configuration initialization where we supply an auth config and a ledgerClientUrl: -``` typescript -import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk' +```typescript +import { SDK, localNetStaticConfig } from "@canton-network/wallet-sdk"; export default async function () { - const sdk = await SDK.create({ - auth: { - method: 'self_signed', - issuer: 'unsafe-auth', - credentials: { - clientId: 'ledger-api-user', - clientSecret: 'unsafe', - audience: 'https://canton.network.global', - scope: '', - }, - }, - ledgerClientUrl: new URL('http://localhost:2975'), - token: { - validatorUrl: new URL('http://localhost:2000/api/validator'), - registries: [ - new URL('http://localhost:2000/api/validator/v0/scan-proxy'), - ], - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - }, - amulet: { - validatorUrl: localNetStaticConfig.LOCALNET_APP_VALIDATOR_URL, - scanApiUrl: localNetStaticConfig.LOCALNET_SCAN_API_URL, - auth: TOKEN_PROVIDER_CONFIG_DEFAULT, - registryUrl: localNetStaticConfig.LOCALNET_REGISTRY_API_URL, - }, - asset: { - registries: [localNetStaticConfig.LOCALNET_REGISTRY_API_URL], - auth: TOKEN_PROVIDER_CONFIG_DEFAULT, - }, - }) - - const myParty = global.EXISTING_PARTY_1 - - await sdk.token.utxos.list({ partyId: myParty }) - - await sdk.amulet.traffic.status() - - // OR, you can defer loading config by calling .extend() - - const basicSDK = await SDK.create({ - auth: { - method: 'self_signed', - issuer: 'unsafe-auth', - credentials: { - clientId: 'ledger-api-user', - clientSecret: 'unsafe', - audience: 'https://canton.network.global', - scope: '', - }, - }, - ledgerClientUrl: new URL('http://localhost:2975'), - }) - - // Extend with token namespace - const tokenExtendedSDK = await basicSDK.extend({ - token: { - validatorUrl: new URL('http://localhost:2000/api/validator'), - registries: [ - new URL('http://localhost:2000/api/validator/v0/scan-proxy'), - ], - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - }, - }) - - // Now token namespace is available - await tokenExtendedSDK.token.utxos.list({ partyId: myParty }) - - // Can extend further with more namespaces - const fullyExtendedSDK = await tokenExtendedSDK.extend({ - amulet: { - validatorUrl: localNetStaticConfig.LOCALNET_APP_VALIDATOR_URL, - scanApiUrl: localNetStaticConfig.LOCALNET_SCAN_API_URL, - auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, - registryUrl: localNetStaticConfig.LOCALNET_REGISTRY_API_URL, - }, - }) - - // Now both token and amulet are available - await fullyExtendedSDK.token.utxos.list({ partyId: myParty }) - await fullyExtendedSDK.amulet.traffic.status() + const sdk = await SDK.create({ + auth: { + method: "self_signed", + issuer: "unsafe-auth", + credentials: { + clientId: "ledger-api-user", + clientSecret: "unsafe", + audience: "https://canton.network.global", + scope: "", + }, + }, + ledgerClientUrl: new URL("http://localhost:2975"), + token: { + registries: [ + new URL("http://localhost:2000/api/validator/v0/scan-proxy"), + ], + auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, + }, + amulet: { + scanApiUrl: localNetStaticConfig.LOCALNET_SCAN_API_URL, + auth: TOKEN_PROVIDER_CONFIG_DEFAULT, + registryUrl: localNetStaticConfig.LOCALNET_REGISTRY_API_URL, + }, + asset: { + registries: [localNetStaticConfig.LOCALNET_REGISTRY_API_URL], + auth: TOKEN_PROVIDER_CONFIG_DEFAULT, + }, + }); + + const myParty = global.EXISTING_PARTY_1; + + await sdk.token.utxos.list({ partyId: myParty }); + + await sdk.amulet.traffic.status(); + + // OR, you can defer loading config by calling .extend() + + const basicSDK = await SDK.create({ + auth: { + method: "self_signed", + issuer: "unsafe-auth", + credentials: { + clientId: "ledger-api-user", + clientSecret: "unsafe", + audience: "https://canton.network.global", + scope: "", + }, + }, + ledgerClientUrl: new URL("http://localhost:2975"), + }); + + // Extend with token namespace + const tokenExtendedSDK = await basicSDK.extend({ + token: { + validatorUrl: new URL("http://localhost:2000/api/validator"), + registries: [ + new URL("http://localhost:2000/api/validator/v0/scan-proxy"), + ], + auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, + }, + }); + + // Now token namespace is available + await tokenExtendedSDK.token.utxos.list({ partyId: myParty }); + + // Can extend further with more namespaces + const fullyExtendedSDK = await tokenExtendedSDK.extend({ + amulet: { + validatorUrl: localNetStaticConfig.LOCALNET_APP_VALIDATOR_URL, + scanApiUrl: localNetStaticConfig.LOCALNET_SCAN_API_URL, + auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT, + registryUrl: localNetStaticConfig.LOCALNET_REGISTRY_API_URL, + }, + }); + + // Now both token and amulet are available + await fullyExtendedSDK.token.utxos.list({ partyId: myParty }); + await fullyExtendedSDK.amulet.traffic.status(); } ``` Provider intialization: The provider is an abstraction that ultimately interacts with the Ledger (JSON LAPI). This can be implemented for either a dApp consumer, direct ledger user, or alternative transport channels such as Wallet Connect. -``` javascript +```javascript // Notice that `auth` and `ledgerClientUrl` are no longer needed // when supplying sdk with custom provider -const sdk = await SDK.create(config, provider) +const sdk = await SDK.create(config, provider); ``` ## Namespace changes @@ -138,7 +136,8 @@ Jump to the page that matches the work you are migrating: icon="user-gear" href="/sdks-tools/sdks/wallet-sdk/using-the-sdk/v0-to-v1-migration/user" > - Create users and grant rights without separate admin/user ledger controllers. + Create users and grant rights without separate admin/user ledger + controllers. -``` javascript -sdk.setPartyId(myPartyId) -const holdingTransactionsmyPartyId = await sdk.tokenStandard?.listHoldingTransactions() -sdk.setPartyId(myPartyId2) -const holdingTransactionsmyPartyId2 = await sdk.tokenStandard?.listHoldingTransactions() +```javascript +sdk.setPartyId(myPartyId); +const holdingTransactionsmyPartyId = + await sdk.tokenStandard?.listHoldingTransactions(); +sdk.setPartyId(myPartyId2); +const holdingTransactionsmyPartyId2 = + await sdk.tokenStandard?.listHoldingTransactions(); ``` --- -``` javascript -const holdingTransactionsmyPartyId = await token.holdings(myPartyId) -const holdingTransactionsmyPartyId2 = await token.holdings(myPartyId2) +```javascript +const holdingTransactionsmyPartyId = await token.holdings(myPartyId); +const holdingTransactionsmyPartyId2 = await token.holdings(myPartyId2); ``` @@ -207,15 +208,15 @@ In v0, the controllers and sdk were stateful. In v1, party information should be The **keys** namespace is always available on the basic SDK. Use it instead of standalone key-pair helpers: -| v0 | v1 | -| --- | --- | +| v0 | v1 | +| ----------------- | --------------------- | | `createKeyPair()` | `sdk.keys.generate()` | The **events** namespace replaces ledger update and completion subscriptions from `userLedger`. Like `amulet`, `token`, and `asset`, it is an extended namespace that you configure at creation time or via `.extend()`: -| v0 | v1 | -| --- | --- | -| `sdk.userLedger.subscribeToUpdates` | `sdk.events.updates` | +| v0 | v1 | +| --------------------------------------- | ------------------------ | +| `sdk.userLedger.subscribeToUpdates` | `sdk.events.updates` | | `sdk.userLedger.subscribeToCompletions` | `sdk.events.completions` | For the complete method map across all namespaces, see the [migration cheat sheet](/sdks-tools/sdks/wallet-sdk/using-the-sdk/v0-to-v1-migration/migration-cheat-sheet).