Wallet SDK Configuration

If you have already played around with the wallet SDK you might have come across snippets like:

import {
    WalletSDKImpl,
    localNetAuthDefault,
    localNetLedgerDefault,
    localNetTopologyDefault,
    localNetTokenStandardDefault,
    localValidatorDefault,
} from '@canton-network/wallet-sdk'

// @disable-snapshot-test
export default async function () {
    // it is important to configure the SDK correctly else you might run into connectivity or authentication issues
    return new WalletSDKImpl().configure({
        logger: console,
        authFactory: localNetAuthDefault,
        ledgerFactory: localNetLedgerDefault,
        topologyFactory: localNetTopologyDefault,
        tokenStandardFactory: localNetTokenStandardDefault,
        validatorFactory: localValidatorDefault,
    })
}

This is the default config that can be used in combination with a non-altered Localnet running instance.

However as soon as you need to migrate your script, code and deployment to a different environment these default configurations are no longer viable to use. In those cases creating custom factories for each controller is needed. Here is a template that you can use when setting up your own custom connectivity configuration:

import {
    WalletSDKImpl,
    LedgerController,
    TopologyController,
    ValidatorController,
    localNetAuthDefault,
} from '@canton-network/wallet-sdk'

// @disable-snapshot-test
export default async function () {
    const myLedgerFactory = (userId: string, token: string) => {
        return new LedgerController(
            userId,
            new URL('http://my-json-ledger-api'),
            token
        )
    }

    const myTopologyFactory = (
        userId: string,
        userAdminToken: string,
        synchronizerId: string
    ) => {
        return new TopologyController(
            'my-grpc-admin-api',
            new URL('http://my-json-ledger-api'),
            userId,
            userAdminToken,
            synchronizerId
        )
    }

    const myValidatorFactory = (userId: string, token: string) => {
        return new ValidatorController(
            userId,
            new URL('http://my-validator-app-api'),
            token
        )
    }

    const sdk = new WalletSDKImpl().configure({
        logger: console,
        authFactory: localNetAuthDefault,
        ledgerFactory: myLedgerFactory,
        topologyFactory: myTopologyFactory,
        validatorFactory: myValidatorFactory,
    })

    await sdk.connect()
    await sdk.connectAdmin()
    //an alternative here is the use the synchronizer directly like
    //await sdk.connectTopology('global-domain::22200...')
    await sdk.connectTopology(new URL('http://my-scan-proxy-api'))
}

you dont need to configure all controllers every time, for instance the topologyController is only need if you are creating a new external party.

How do validate my configurations?

Knowing if you are using the correct url and port can be daunting, here is a few curl gcurl commands you can use to validate against an expected output

my-json-ledger-api can be identified with curl http://${my-json-ledger-api}/v2/version it should produce a json that looks like

{
   "version":"3.3.0-SNAPSHOT",
   "features":{
      "experimental":{
         "staticTime":{
            "supported":false
         },
         "commandInspectionService":{
            "supported":true
         }
      },
      "userManagement":{
         "supported":true,
         "maxRightsPerUser":1000,
         "maxUsersPageSize":1000
      },
      "partyManagement":{
         "maxPartiesPageSize":10000
      },
      "offsetCheckpoint":{
         "maxOffsetCheckpointEmissionDelay":{
            "seconds":75,
            "nanos":0,
            "unknownFields":{
               "fields":{

               }
            }
         }
      }
   }
}

the fields may vary based on your configuration.

my-grpc-admin-api can be identified with grpcurl -plaintext ${my-grpc-admin-api} list it should produce an output like

com.digitalasset.canton.admin.health.v30.StatusService
com.digitalasset.canton.admin.participant.v30.EnterpriseParticipantReplicationService
com.digitalasset.canton.admin.participant.v30.PackageService
com.digitalasset.canton.admin.participant.v30.ParticipantInspectionService
com.digitalasset.canton.admin.participant.v30.ParticipantRepairService
com.digitalasset.canton.admin.participant.v30.ParticipantStatusService
com.digitalasset.canton.admin.participant.v30.PartyManagementService
com.digitalasset.canton.admin.participant.v30.PingService
com.digitalasset.canton.admin.participant.v30.PruningService
com.digitalasset.canton.admin.participant.v30.ResourceManagementService
com.digitalasset.canton.admin.participant.v30.SynchronizerConnectivityService
com.digitalasset.canton.admin.participant.v30.TrafficControlService
com.digitalasset.canton.connection.v30.ApiInfoService
com.digitalasset.canton.crypto.admin.v30.VaultService
com.digitalasset.canton.time.admin.v30.SynchronizerTimeService
com.digitalasset.canton.topology.admin.v30.IdentityInitializationService
com.digitalasset.canton.topology.admin.v30.TopologyAggregationService
com.digitalasset.canton.topology.admin.v30.TopologyManagerReadService
com.digitalasset.canton.topology.admin.v30.TopologyManagerWriteService
grpc.reflection.v1alpha.ServerReflection

the list might differed based on you canton configuration, the most important part is TopologyManagerReadService & TopologyManagerWriteService

my-validator-app-api & my-scan-proxy-api can both be identified with curl ${api}/version they both produce an output like

{"version":"0.4.15","commit_ts":"2025-09-05T11:38:13Z"}