Documentation/canton-network-docs/SDKsWallet SDKUsing the SDKv0 to v1 migrationView on canton-network-docs ↗
canton-network-docs/SDKsWallet SDKUsing the SDKv0 to v1 migration
User Namespace
The user namespace provides methods for user management on the Canton Network.
Granting user rights
The below example demonstrates the full usage of the feature:
Availability
The user namespace is always available as part of the basic SDK interface. It’s initialized automatically when you create an SDK instance and doesn’t require additional configuration viaextend().
import { localNetStaticConfig, SDK } from '@canton-network/wallet-sdk'
export default async function () {
const sdk = await SDK.create({
auth: TOKEN_PROVIDER_CONFIG_DEFAULT,
ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL,
})
const primaryParty = EXISTING_PARTY_1
const userId = 'user-id'
// user namespace is immediately available
await sdk.user.create({ userId, primaryParty })
}
Key changes from v0 to v1
The distinction betwen the user ledger and admin ledger have been removed. Instead, the token is used to determine whether a user has admin rights. Creating usersawait sdk.adminLedger.createUser('userId', primaryParty)
const result = await sdk.user
.create({
userId: 'userId',
primaryParty: primaryParty,
userRights: {...}
})
await sdk.userLedger.grantRights([actAsRights], [readAsRights])
const result = await sdk.rights
.grant({
userRights: {...},
userId: {'userId'}, //optional parameter
idp: {'idp'} //optional parameter otherwise will use default IDP
})
Full example: multi-user setup and rights
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')
}
See all 189 lines
Migration reference
| v0 method | v1 method |
|---|---|
sdk.adminLedger.createUser | sdk.user.create |
sdk.userLedger.grantRights | sdk.user.rights.grant |
See also
- v0 to v1 migration overview
- Migration cheat sheet
- Configuration — SDK configuration
- User management — User management overview
Was this page helpful?
⌘I