@ledgerhq/revault-sdk 0.16.1 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/bake.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bake/index.ts","../src/bake/bake-pledge.ts","../src/bake/utils.ts","../src/bake/bake-tradelink-organization.ts","../src/bake/bake-workspace.ts","../src/bake/types.ts"],"sourcesContent":["import invariant from \"invariant\";\n\nimport type { Logger } from \"@/types\";\n\nimport { bakePledgeAdjustment } from \"./bake-pledge\";\nimport { bakeTradelinkOrganization } from \"./bake-tradelink-organization\";\nimport { bakeWorkspace } from \"./bake-workspace\";\nimport type { BakeOptions } from \"./types\";\n\nexport * from \"./bake-pledge\";\n\nexport * from \"./types\";\n\nexport { createAndApproveRequest } from \"./utils\";\n\nexport async function bakeManifest(options: BakeOptions, logger: Logger): Promise<void> {\n const {\n engine,\n workspaceName,\n rootAuthToken,\n manifest: { tradelink, workspace },\n } = options;\n\n if (tradelink) {\n invariant(rootAuthToken, `rootAuthToken is required to create Tradelink org entities`);\n await bakeTradelinkOrganization(\n {\n engine,\n tradelink,\n rootAuthToken,\n ...(workspace?.tradelink?.networkBlueprint && workspaceName\n ? { networkBlueprint: { blueprint: workspace.tradelink.networkBlueprint, workspaceName } }\n : {}),\n },\n logger,\n );\n }\n\n if (workspace) {\n invariant(workspaceName, `Can't bake workspace without specifying a workspace name`);\n await bakeWorkspace({ engine, workspace, workspaceName }, logger);\n\n if (workspace.pledges) {\n const engineWithWorkspace = engine.withWorkspace(workspaceName);\n for (const pledgeAdjustment of workspace.pledges) {\n await bakePledgeAdjustment({ engine: engineWithWorkspace, pledgeAdjustment }, logger);\n }\n }\n }\n\n logger.info(\"Successfully baked\");\n}\n","import invariant from \"invariant\";\n\nimport type { Engine, WithWorkspace } from \"@/engine\";\nimport type { Logger } from \"@/types\";\nimport { createDeviceIndexResolver, fetchAll } from \"@/utils\";\n\nimport type { ManifestPledgeAdjustment } from \"./types\";\nimport { createAndApproveRequest } from \"./utils\";\n\ntype Options = {\n engine: Engine<WithWorkspace>;\n pledgeAdjustment: ManifestPledgeAdjustment;\n};\n\nconst flattenApprovers = (groups: { quorum: number; userIds: string[] }[]): string[] => {\n return groups.reduce<string[]>((acc, cur) => {\n acc.push(...cur.userIds.slice(0, cur.quorum));\n return acc;\n }, []);\n};\n\nexport async function bakePledgeAdjustment(options: Options, logger: Logger): Promise<void> {\n const { pledgeAdjustment, engine } = options;\n\n const getDeviceIndex = createDeviceIndexResolver(engine);\n\n logger.info(\"Logging in with admin...\");\n const admin = await engine.withDeviceIndex(4).login();\n\n logger.info(\"Fetching account, tradelink blueprint and network...\");\n const [matchingAccounts, blueprint, network] = await Promise.all([\n fetchAll(admin.client.accounts.list.query, { name: pledgeAdjustment.account }),\n admin.client.tradelink.getNetworkBlueprint.query(),\n admin.client.tradelink.getNetwork.query(),\n ]);\n\n const account = matchingAccounts.find((account) => account.name === pledgeAdjustment.account);\n invariant(account, `Account ${pledgeAdjustment.account} not found`);\n\n invariant(blueprint, \"Tradelink blueprint is not created yet\");\n invariant(network, \"Tradelink network is not created yet\");\n\n const exchange = network.exchanges.find((exchange) => {\n const blueprintExchange = blueprint.exchanges.find(\n (blueprintExchange) => blueprintExchange.tradelinkId === exchange.tradelinkId,\n );\n invariant(blueprintExchange, `Exchange ${exchange.tradelinkId} not found in blueprint`);\n return blueprintExchange.name === pledgeAdjustment.exchange;\n });\n invariant(exchange, `Exchange ${pledgeAdjustment.exchange} not found in network`);\n\n const governance = account.governance;\n invariant(governance.type === \"TRADELINK\", \"Account governance is not TRADELINK\");\n const assetManager = network.assetManagers.find((am) => am.id === governance.assetManagerId);\n invariant(assetManager, `Asset manager ${governance.assetManagerId} not found in network`);\n\n const exchangeIsConfiguredForAccount = !!governance.exchangeConfigs.find(\n (e) => e.exchangeId === exchange.id,\n );\n invariant(\n exchangeIsConfiguredForAccount,\n `Exchange ${exchange.id} is not configured for account ${account.id}`,\n );\n\n const approverIds = [\n ...flattenApprovers(assetManager.groups),\n ...flattenApprovers(exchange.groups),\n ];\n\n const approvers = await Promise.all(\n approverIds.map((id) =>\n admin.client.users.findById\n .query({ id })\n .then((user) => getDeviceIndex(user.deviceUserId!))\n .then((index) => engine.withDeviceIndex(index).login()),\n ),\n );\n\n await createAndApproveRequest(\n {\n type: \"ADJUST_PLEDGE\",\n data: {\n accountId: account.id,\n exchangeId: exchange.id,\n amount: pledgeAdjustment.amount,\n },\n },\n approvers,\n logger,\n );\n\n logger.info(\n `Successfully adjusted pledge for account ${pledgeAdjustment.account} on exchange ${pledgeAdjustment.exchange}`,\n );\n}\n","import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { Engine, WithDevice, WithPsdAuth, WithWorkspace } from \"@/engine\";\nimport type { RouterInputs } from \"@/trpc\";\nimport type { Logger } from \"@/types\";\n\ntype LogFunction = (msg: string) => void;\n\ntype LogHelpers = {\n logTitle: LogFunction;\n logStep: LogFunction;\n logSubStep: LogFunction;\n};\n\nexport function createBakeLogHelpers(logger: Logger): LogHelpers {\n return {\n logTitle(title: string): void {\n logger.info(`:: ${title} ::`);\n },\n logStep(msg: string): void {\n logger.info(`=> ${msg}`);\n },\n logSubStep(msg: string): void {\n logger.info(` -> ${msg}`);\n },\n };\n}\n\nexport type CreateRequestInput = RouterInputs[\"requests\"][\"create\"][\"request\"];\n\nexport type inferRequestInputData<T extends RouterInputs[\"requests\"][\"create\"][\"request\"][\"type\"]> =\n Extract<RouterInputs[\"requests\"][\"create\"][\"request\"], { type: T }>[\"data\"];\n\nexport async function approveRequest(\n request: VaultRequestResponse,\n approvers: Engine<WithWorkspace & WithDevice & WithPsdAuth>[],\n logger: Logger,\n): Promise<VaultRequestResponse> {\n const { logSubStep } = createBakeLogHelpers(logger);\n for (let i = 0; i < approvers.length; i++) {\n logSubStep(`Collecting approval (${i + 1}/${approvers.length})...`);\n const approver = approvers[i]!;\n request = await approver.approve(request);\n }\n return request;\n}\n\nexport async function createAndApproveRequest(\n input: CreateRequestInput,\n approvers: Engine<WithWorkspace & WithDevice & WithPsdAuth>[],\n logger: Logger,\n): Promise<VaultRequestResponse> {\n const { logSubStep } = createBakeLogHelpers(logger);\n const creator = approvers[0];\n invariant(creator, \"Need at least 1 user to create a request\");\n logSubStep(`Creating request of type ${input.type}...`);\n const request = await creator.client.requests.create.mutate({ request: input });\n return approveRequest(request, approvers, logger);\n}\n","import type { Logger } from \"@/types\";\n\nimport type { BakeOptions, ManifestTradelinkNetworkBlueprint, ManifestTradelinkOrg } from \"./types\";\nimport { createBakeLogHelpers } from \"./utils\";\n\ntype Options = Omit<BakeOptions, \"manifest\" | \"rootAuthToken\"> & {\n tradelink: ManifestTradelinkOrg;\n rootAuthToken: string;\n networkBlueprint?: { workspaceName: string; blueprint: ManifestTradelinkNetworkBlueprint };\n};\n\nexport async function bakeTradelinkOrganization(options: Options, logger: Logger): Promise<void> {\n const { tradelink, engine, rootAuthToken, networkBlueprint } = options;\n\n const { logStep } = createBakeLogHelpers(logger);\n\n const rootClient = engine.createClient({ rootAuthToken });\n if (tradelink.exchanges) {\n logStep(\"Creating Tradelink organization exchanges...\");\n const existingOrgExchanges = await rootClient.tradelink.root.listOrgExchanges.query();\n for (const orgExchange of tradelink.exchanges) {\n const existingOrgExchange = existingOrgExchanges.find((e) => e.name === orgExchange.name);\n if (existingOrgExchange) {\n logger.info(\n `[SKIPPED] Organization exchange ${existingOrgExchange.name} (${existingOrgExchange.code}) already exists`,\n );\n } else {\n await rootClient.tradelink.root.createOrgExchange.mutate({\n code: orgExchange.code,\n name: orgExchange.name,\n logoUrl: orgExchange.logo,\n });\n logger.info(`Created organization exchange ${orgExchange.name} (${orgExchange.code})`);\n }\n }\n }\n if (tradelink.assetManagers) {\n logStep(\"Creating Tradelink organization asset managers...\");\n const existingAssetManagers = await rootClient.tradelink.root.listOrgAssetManagers.query();\n for (const orgAssetManager of tradelink.assetManagers) {\n const existingOrgAssetManager = existingAssetManagers.find(\n (e) => e.name === orgAssetManager.name,\n );\n if (existingOrgAssetManager) {\n logger.info(\n `[SKIPPED] Organization asset manager ${existingOrgAssetManager.name} (${existingOrgAssetManager.code}) already exists`,\n );\n } else {\n await rootClient.tradelink.root.createOrgAssetManager.mutate({\n code: orgAssetManager.code,\n name: orgAssetManager.name,\n logoUrl: orgAssetManager.logo,\n });\n logger.info(\n `Created organization asset manager ${orgAssetManager.name} (${orgAssetManager.code})`,\n );\n }\n }\n }\n if (tradelink.custodians) {\n logStep(\"Creating Tradelink organization custodians...\");\n const existingCustodians = await rootClient.tradelink.root.listOrgCustodians.query();\n for (const orgCustodian of tradelink.custodians) {\n const existingOrgCustodian = existingCustodians.find((e) => e.name === orgCustodian.name);\n if (existingOrgCustodian) {\n logger.info(\n `[SKIPPED] Organization custodian ${existingOrgCustodian.name} (${existingOrgCustodian.code}) already exists`,\n );\n } else {\n await rootClient.tradelink.root.createOrgCustodian.mutate({\n code: orgCustodian.code,\n name: orgCustodian.name,\n logoUrl: orgCustodian.logo,\n });\n logger.info(`Created organization custodian ${orgCustodian.name} (${orgCustodian.code})`);\n }\n }\n }\n if (networkBlueprint) {\n logStep(\"Creating Tradelink network blueprint...\");\n const { workspaceName, blueprint } = networkBlueprint;\n const existingBlueprints = await rootClient.tradelink.root.listNetworkBlueprints.query();\n const existingBlueprint = existingBlueprints.find((e) => e.workspaceName === workspaceName);\n if (existingBlueprint) {\n logger.info(`[SKIPPED] Network blueprint for ${workspaceName} workspace already exists`);\n } else {\n await rootClient.tradelink.root.createNetworkBlueprint.mutate({\n workspaceName,\n custodian: { name: blueprint.custodian },\n exchanges: blueprint.exchanges.map((_) => ({ name: _ })),\n assetManagers: blueprint.assetManagers.map((_) => ({ name: _ })),\n });\n logger.info(`Created network blueprint for ${networkBlueprint.workspaceName} workspace`);\n }\n }\n}\n","import type {\n CurrencyResponse,\n ReviewStepWithUsers,\n TokenResponse,\n TradelinkNetworkBlueprintResponse,\n UserResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport _ from \"lodash\";\n\nimport type { Logger } from \"@/types\";\nimport { createDeviceIndexResolver, fetchAll } from \"@/utils\";\n\nimport type {\n BakeOptions,\n ManifestAccount,\n ManifestApiUser,\n ManifestGovernanceRule,\n ManifestGroup,\n ManifestPolicy,\n ManifestTradelinkEntity,\n ManifestTradelinkGroup,\n ManifestTradelinkNetwork,\n ManifestWhitelist,\n ManifestWorkspace,\n} from \"./types\";\nimport {\n type CreateRequestInput,\n approveRequest,\n createAndApproveRequest,\n createBakeLogHelpers,\n type inferRequestInputData,\n} from \"./utils\";\n\ntype GovRuleData = inferRequestInputData<\"CREATE_POLICY\">[\"govRules\"][number];\n\ntype Options = Omit<BakeOptions, \"manifest\" | \"workspaceName\"> & {\n workspace: ManifestWorkspace;\n workspaceName: string;\n};\n\nexport async function bakeWorkspace(options: Options, logger: Logger): Promise<void> {\n const { workspace, engine, workspaceName } = options;\n\n const workspaceEngine = engine.withWorkspace(workspaceName);\n const { logTitle, logStep, logSubStep } = createBakeLogHelpers(logger);\n\n // utility to retrieve device index based on device user id\n const findDeviceIndex = createDeviceIndexResolver(workspaceEngine);\n\n // Log-in once with the two admins (index 4 & 5 by convention) that will create all\n // the requests for the manifest objects.\n logger.info(\"Authenticating with two admins...\");\n const [admin1, admin2] = await Promise.all([\n workspaceEngine.withDeviceIndex(4).login(),\n workspaceEngine.withDeviceIndex(5).login(),\n ]);\n\n // Retrieve all existing data, so we are then able to skip creating stuff when not needed.\n logger.info(\"Fetching existing data...\");\n const [\n existingUsers,\n existingGroups,\n existingPolicies,\n existingAccounts,\n tradelinkNetworkBlueprint,\n ] = await Promise.all([\n fetchAll(admin1.client.users.list.query, { status: \"ACTIVE\" }),\n fetchAll(admin1.client.groups.list.query, { status: \"ACTIVE\" }),\n fetchAll(admin1.client.policies.list.query, { isPrivate: false }),\n fetchAll(admin1.client.accounts.list.query, { status: \"ACTIVE\", skipLiveData: true }),\n admin1.client.tradelink.getNetworkBlueprint.query(),\n ]);\n\n const tradelinkOrgExchangesByName = _.keyBy(tradelinkNetworkBlueprint?.exchanges, \"name\");\n const tradelinkOrgAssetManagersByName = _.keyBy(tradelinkNetworkBlueprint?.assetManagers, \"name\");\n\n let existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n\n // Merge admins & operators (we can't fetch all users in a row because we don't want API users,\n // and we don't have a way to retrieve both admins & operators in a single fetch)\n const existingPsdUsers = existingUsers.filter((user) => user.deviceType === \"PSD\");\n const existingApiUsers = existingUsers.filter((user) => user.deviceType === \"API\");\n // Retrieve all device indexes for the existing users\n const usersWithDeviceIndex = await resolveDevicesIndexes(existingPsdUsers);\n\n // ---------------------------------\n // USERS\n // ---------------------------------\n if (workspace.users) {\n logTitle(\"Users\");\n if (workspace.users.admins) {\n for (const deviceIndex of workspace.users.admins) {\n await createUser(\"ADMIN\", deviceIndex);\n }\n }\n if (workspace.users.operators) {\n for (const deviceIndex of workspace.users.operators) {\n await createUser(\"OPERATOR\", deviceIndex);\n }\n }\n if (workspace.users.api) {\n for (const apiUser of workspace.users.api) {\n await createApiUser(apiUser);\n }\n }\n }\n\n // ---------------------------------\n // GROUPS\n // ---------------------------------\n if (workspace.groups) {\n logTitle(\"Groups\");\n for (const group of workspace.groups) {\n await createGroup(group);\n }\n }\n\n // ---------------------------------\n // WHITELISTS\n // ---------------------------------\n if (workspace.whitelists) {\n logTitle(\"Whitelists\");\n await createWhitelists(workspace.whitelists);\n }\n\n // POLICIES\n // ---------------------------------\n if (workspace.policies) {\n logTitle(\"Policies\");\n for (const policy of workspace.policies) {\n await createPolicy(policy);\n }\n }\n\n // ---------------------------------\n // TRADELINK NETWORK\n // ---------------------------------\n if (workspace.tradelink) {\n logTitle(\"Tradelink\");\n await createTradelink(workspace.tradelink);\n }\n\n // ---------------------------------\n // ACCOUNTS\n // ---------------------------------\n if (workspace.accounts) {\n logTitle(\"Accounts\");\n for (const account of workspace.accounts) {\n await createAccount(account);\n }\n }\n\n async function createWhitelists(whitelists: ManifestWhitelist[]): Promise<void> {\n const existingWhitelists = await fetchAll(admin1.client.whitelists.list.query, {\n status: \"ACTIVE\",\n });\n for (const whitelist of whitelists) {\n await createWhitelist(whitelist);\n }\n\n async function createWhitelist(whitelist: ManifestWhitelist): Promise<void> {\n const existing = existingWhitelists.find((w) => w.name === whitelist.name);\n\n // TODO: compare with existing to eventually do an EDIT\n if (existing) {\n logger.info(`[SKIPPED] Whitelist \"${whitelist.name}\" already exists`);\n return;\n }\n\n const input: CreateRequestInput = {\n type: \"CREATE_WHITELIST\",\n data: whitelist,\n };\n\n await createAndApproveRequest(input, [admin1, admin2], logger);\n logSubStep(`Whitelist \"${whitelist.name}\" has been created`);\n }\n }\n\n function govRuleFromManifest(rule: ManifestGovernanceRule): GovRuleData {\n return {\n operationType: rule.type,\n reviewSteps: rule.steps.map((step) => {\n if (\"group\" in step) {\n return {\n quorum: step.quorum,\n groupId: groupIdFromName(step.group),\n };\n }\n return {\n quorum: step.quorum,\n userIds: step.members.map(userIdFromDeviceIndex),\n };\n }),\n };\n }\n\n async function createAccount(account: ManifestAccount): Promise<void> {\n const existing = existingAccounts.find((a) => a.name === account.name);\n if (existing) {\n logger.info(`[SKIPPED] Account \"${account.name}\" already exists`);\n return;\n }\n logStep(`Creating account \"${account.name}\"`);\n logSubStep(\"Fetching account asset...\");\n const asset = await fetchAsset({\n currency: account.currency,\n contractAddress: account.contractAddress,\n });\n const input: CreateRequestInput = {\n type: \"CREATE_ACCOUNT\",\n data: {\n // general fields\n name: account.name,\n\n // asset fields\n type: asset.type,\n currency: account.currency,\n index: account.index,\n contractAddress: account.contractAddress,\n\n // governance fields\n governance:\n account.governance.type === \"TRADELINK\"\n ? {\n type: \"TRADELINK\",\n assetManagerId: assetManagerIdFromName(account.governance.assetManager),\n exchangeConfigs: account.governance.exchanges.map((exchangeConfig) => ({\n exchangeId: exchangeIdFromName(exchangeConfig.name),\n repledgeAuthorized: exchangeConfig.repledgeAuthorized === true,\n needsAssetManagerApprovalForSettlements:\n exchangeConfig.needsAssetManagerApprovalForSettlements === true,\n })),\n }\n : {\n type: \"CLASSIC\",\n policy: { rules: account.governance.rules.map(govRuleFromManifest) },\n },\n },\n };\n\n const req = await createAndApproveRequest(input, [admin1, admin2], logger);\n\n if (account.governance.type === \"TRADELINK\") {\n logStep(`Activating tradelink account \"${account.name}\"`);\n // we need to activate the account with the asset manager\n const assetManagerId = assetManagerIdFromName(account.governance.assetManager);\n const assetManager = existingTradelinkNetwork?.assetManagers.find(\n (assetManager) => assetManager.id === assetManagerId,\n );\n invariant(assetManager, `Asset manager for account exists`);\n const loggedAssetManagerOperators = await Promise.all(\n assetManager.groups.flatMap(({ quorum, userIds }) =>\n userIds.slice(0, quorum).map((userId) => {\n const deviceIndex = usersWithDeviceIndex.find((o) => o.user.id === userId)?.deviceIndex;\n return workspaceEngine.withDeviceIndex(deviceIndex!).login();\n }),\n ),\n );\n await createAndApproveRequest(\n { type: \"ACTIVATE_TRADELINK_ACCOUNT\", targetId: req.targetId!, data: {} },\n loggedAssetManagerOperators,\n logger,\n );\n }\n\n logSubStep(`Account ${account.name} has been created`);\n }\n\n async function fetchAsset(params: {\n currency: string;\n contractAddress?: string;\n }): Promise<CurrencyResponse | TokenResponse> {\n const { currency, contractAddress } = params;\n if (contractAddress) {\n const tokens = await admin1.client.assets.tokens.query({ search: contractAddress });\n const t = tokens.results.find(\n (t) => t.contractAddress === contractAddress && t.currency === currency,\n );\n invariant(t, `Token ${contractAddress} (${currency}) not found`);\n return t;\n } else {\n const currencies = await admin1.client.assets.currencies.query({});\n const c = currencies.results.find((c) => c.id === currency);\n invariant(c, `Currency ${currency} not found`);\n return c;\n }\n }\n\n async function createUser(role: \"ADMIN\" | \"OPERATOR\", deviceIndex: number): Promise<void> {\n const userEngine = workspaceEngine.withDeviceIndex(deviceIndex);\n const deviceId = await userEngine.device.getDeviceUserId();\n\n // eventually check if we can skip user creation\n const existing = existingUsers.find((user) => user.deviceUserId === deviceId);\n if (existing) {\n logger.info(`[SKIPPED] User with device index ${deviceIndex} already exists`);\n return;\n }\n\n const name = `${role === \"ADMIN\" ? \"Admin\" : \"Operator\"} ${deviceIndex}`;\n logStep(`Creating ${name}`);\n\n logSubStep(\"Creating invitation...\");\n let registration = await admin1.client.userRegistrations.invite.mutate({\n name,\n role,\n deviceUserId: deviceId,\n psdModel: \"STAX\",\n });\n\n logSubStep(\"Completing registration...\");\n registration = await userEngine.register(registration);\n\n logSubStep(\"Creating request...\");\n let req = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_PSD_USER\",\n data: { registrationId: registration.id },\n },\n });\n\n req = await approveRequest(req, [admin1, admin2], logger);\n logSubStep(`${name} has been created`);\n\n const createdUser = await admin1.client.users.findById.query({ id: req.targetId! });\n\n // patch the current state with the newly created user\n existingUsers.push(createdUser);\n usersWithDeviceIndex.push({ user: createdUser, deviceIndex });\n }\n\n async function createApiUser(apiUser: ManifestApiUser): Promise<void> {\n const existing = existingApiUsers.find(\n (user) => user.pubKey === apiUser.pubKey || user.name === apiUser.name,\n );\n if (existing) {\n logger.info(\n `[SKIPPED] API user already exists with name \"${apiUser.name}\" or public key \"${apiUser.pubKey}\"`,\n );\n return;\n }\n\n logStep(`Creating API user \"${apiUser.name}\"...`);\n\n logSubStep(\"Creating request...\");\n let req = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_API_USER\",\n data: {\n name: apiUser.name,\n role: apiUser.role,\n pubKey: apiUser.pubKey,\n viewAll: apiUser.viewAll,\n },\n },\n });\n req = await approveRequest(req, [admin1, admin2], logger);\n logSubStep(`API user \"${apiUser.name}\" has been created`);\n\n logSubStep(\"Generating credentials...\");\n const credentials = await admin1.client.users.resetApiUserCredentials.mutate({\n id: req.targetId!,\n });\n logSubStep(\n `API user \"${apiUser.name}\" credentials have been generated: apiKeyId=${credentials.apiKeyId}, apiKeySecret=${credentials.apiKeySecret}`,\n );\n const createdUser = await admin1.client.users.findById.query({ id: req.targetId! });\n // patch the current state with the newly created user\n existingApiUsers.push(createdUser);\n }\n\n async function createGroup(group: ManifestGroup): Promise<void> {\n const existing = existingGroups.find((g) => g.name === group.name);\n if (existing) {\n logger.info(`[SKIPPED] Group \"${group.name}\" already exists`);\n return;\n }\n\n logStep(`Creating group ${group.name}...`);\n\n const members = group.members.map(userIdFromDeviceIndex);\n\n logSubStep(\"Creating request...\");\n let request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_GROUP\",\n data: {\n name: group.name,\n description: \"\",\n members,\n },\n },\n });\n\n request = await approveRequest(request, [admin1, admin2], logger);\n logSubStep(`${group.name} has been created`);\n\n const createdGroup = await admin1.client.groups.findById.query({ id: request.targetId! });\n existingGroups.push(createdGroup);\n }\n\n async function createPolicy(policy: ManifestPolicy): Promise<void> {\n const existing = existingPolicies.find((p) => p.name === policy.name);\n if (existing) {\n logger.info(`[SKIPPED] Policy \"${policy.name}\" already exists`);\n return;\n }\n\n logStep(`Creating policy ${policy.name}...`);\n\n logSubStep(\"Creating request...\");\n let request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_POLICY\",\n data: {\n name: policy.name,\n currency: policy.currency,\n description: \"\",\n govRules: policy.rules.map(govRuleFromManifest),\n },\n },\n });\n\n request = await approveRequest(request, [admin1, admin2], logger);\n logSubStep(`${policy.name} has been created`);\n\n const createdPolicy = await admin1.client.policies.findById.query({ id: request.targetId! });\n existingPolicies.push(createdPolicy);\n }\n\n async function createTradelink(tradelink: ManifestTradelinkNetwork): Promise<void> {\n if (tradelink.custodian) {\n if (existingTradelinkNetwork === null) {\n logStep(\"Creating custodian config...\");\n const { settlement, withdraw, arbitration } = tradelink.custodian;\n const data = {\n settlement: settlement.map(tradelinkReviewStepFromManifest),\n withdraw: withdraw.map(tradelinkReviewStepFromManifest),\n arbitration: arbitration.map(tradelinkReviewStepFromManifest),\n };\n\n logSubStep(\"Creating request...\");\n const request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_TRADELINK_CUSTODIAN\",\n data,\n },\n });\n\n await approveRequest(request, [admin1, admin2], logger);\n logSubStep(\"Tradelink custodian config has been created\");\n\n existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n } else {\n logger.info(\"[SKIPPED] Custodian config already exists\");\n }\n\n const networkBlueprint = await admin1.client.tradelink.getNetworkBlueprint.query();\n if (networkBlueprint !== null) {\n if (tradelink.exchanges !== undefined) {\n await createTradelinkExchanges(networkBlueprint, tradelink.exchanges);\n }\n\n if (tradelink.assetManagers !== undefined) {\n await createTradelinkAssetManagers(networkBlueprint, tradelink.assetManagers);\n }\n } else {\n logger.error(\n \"Will not create exchanges and asset managers because there is no network blueprint for current workspace\",\n );\n }\n }\n }\n\n async function createTradelinkExchanges(\n networkBlueprint: TradelinkNetworkBlueprintResponse,\n exchanges: ManifestTradelinkEntity[],\n ): Promise<void> {\n invariant(existingTradelinkNetwork !== null, \"Network should exist\");\n const blueprintExchanges = networkBlueprint.exchanges;\n for (const exchange of exchanges) {\n // find uid\n const blueprintExchange = blueprintExchanges.find(({ name }) => name === exchange.name);\n invariant(\n blueprintExchange !== undefined,\n `Exchange ${exchange.name} does not exist in network blueprint`,\n );\n const exchangeId = blueprintExchange.tradelinkId;\n logStep(`Creating exchange ${exchange.name}...`);\n if (\n existingTradelinkNetwork.exchanges.find(({ tradelinkId }) => tradelinkId === exchangeId) !==\n undefined\n ) {\n logger.info(`[SKIPPED] Exchange \"${exchange.name}\" already exists`);\n continue;\n }\n\n logSubStep(\"Creating request...\");\n const request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_TRADELINK_EXCHANGE\",\n data: {\n tradelinkId: exchangeId,\n groups: exchange.groups.map(tradelinkReviewStepFromManifest),\n whitelist: exchange.whitelist,\n },\n },\n });\n\n const loggedExchangeOperators = await Promise.all(\n exchange.groups.flatMap(({ quorum, members }) =>\n members\n .slice(0, quorum)\n .map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login()),\n ),\n );\n\n await approveRequest(request, [admin1, admin2, ...loggedExchangeOperators], logger);\n\n // refresh tradelink network\n existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n invariant(existingTradelinkNetwork !== null, \"Tradelink network exists\");\n }\n }\n\n async function createTradelinkAssetManagers(\n networkBlueprint: TradelinkNetworkBlueprintResponse,\n assetManagers: ManifestTradelinkEntity[],\n ): Promise<void> {\n invariant(existingTradelinkNetwork !== null, \"Network should exist\");\n const blueprintAssetManagers = networkBlueprint.assetManagers;\n for (const assetManager of assetManagers) {\n // find uid\n const blueprintAssetManager = blueprintAssetManagers.find(\n ({ name }) => name === assetManager.name,\n );\n invariant(\n blueprintAssetManager !== undefined,\n `AssetManager ${assetManager.name} does not exist in network blueprint`,\n );\n const assetManagerId = blueprintAssetManager.tradelinkId;\n logStep(`Creating assetManager ${assetManager.name}...`);\n if (\n existingTradelinkNetwork.assetManagers.find(\n ({ tradelinkId }) => tradelinkId === assetManagerId,\n ) !== undefined\n ) {\n logger.info(`[SKIPPED] Asset manager \"${assetManager.name}\" already exists`);\n continue;\n }\n\n logSubStep(\"Creating request...\");\n const request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_TRADELINK_ASSET_MANAGER\",\n data: {\n tradelinkId: assetManagerId,\n groups: assetManager.groups.map(tradelinkReviewStepFromManifest),\n whitelist: assetManager.whitelist,\n },\n },\n });\n\n const loggedAssetManagerOperators = await Promise.all(\n assetManager.groups.flatMap(({ quorum, members }) =>\n members\n .slice(0, quorum)\n .map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login()),\n ),\n );\n\n await approveRequest(request, [admin1, admin2, ...loggedAssetManagerOperators], logger);\n\n // refresh tradelink network\n existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n invariant(existingTradelinkNetwork !== null, \"Tradelink network exists\");\n }\n }\n\n // For each given user, retrieve (by brute force) their device index, by comparing their\n // device user id with the one computed for each tested index.\n // Using .reduce() here to leverage caching existing discoveries\n async function resolveDevicesIndexes(\n users: UserResponse[],\n ): Promise<{ user: UserResponse; deviceIndex: number }[]> {\n const usersWithDeviceIndex = await users.reduce<\n Promise<{ user: UserResponse; deviceIndex: number }[]>\n >(\n (acc, cur) =>\n acc.then(async (acc) => {\n acc.push(await withDeviceIndex(cur));\n return acc;\n }),\n Promise.resolve([]),\n );\n return usersWithDeviceIndex;\n }\n\n async function withDeviceIndex(\n user: UserResponse,\n ): Promise<{ user: UserResponse; deviceIndex: number }> {\n invariant(user.deviceUserId, `User ${user.id} does not have any device user id`);\n const deviceIndex = await findDeviceIndex(user.deviceUserId);\n return { user, deviceIndex };\n }\n\n function userIdFromDeviceIndex(deviceIndex: number): string {\n const corresponding = usersWithDeviceIndex.find((o) => o.deviceIndex === deviceIndex);\n invariant(corresponding, `No user with device index ${deviceIndex}`);\n return corresponding.user.id;\n }\n\n function groupIdFromName(groupName: string): string {\n const group = existingGroups.find((g) => g.name === groupName);\n invariant(group, `Group ${groupName} not found`);\n return group.id;\n }\n\n function assetManagerIdFromName(assetManagerName: string): string {\n const orgAssetManager = tradelinkOrgAssetManagersByName[assetManagerName];\n invariant(\n orgAssetManager,\n `Can't find Tradelink organization asset manager ${assetManagerName}`,\n );\n const assetManager = existingTradelinkNetwork?.assetManagers.find(\n (assetManager) => assetManager.tradelinkId === orgAssetManager.tradelinkId,\n );\n invariant(assetManager, `Can't find Tradelink assetManager ${assetManagerName}`);\n return assetManager.id;\n }\n\n function exchangeIdFromName(exchangeName: string): string {\n const exchange = existingTradelinkNetwork?.exchanges.find((exchange) => {\n const orgExchange = tradelinkOrgExchangesByName[exchangeName];\n invariant(orgExchange, `Can't find Tradelink organization exchange ${exchange.tradelinkId}`);\n return orgExchange.name === exchangeName;\n });\n invariant(exchange, `Can't find Tradelink exchange ${exchangeName}`);\n return exchange.id;\n }\n\n function tradelinkReviewStepFromManifest({\n members,\n quorum,\n }: ManifestTradelinkGroup): ReviewStepWithUsers {\n return {\n userIds: members.map(userIdFromDeviceIndex),\n quorum,\n };\n }\n}\n","import z from \"zod\";\n\nimport type { Engine } from \"@/engine\";\n\n// #region ---------- General types ---------------------------------------------------------------\n\nexport type BakeOptions = {\n manifest: Manifest;\n engine: Engine;\n workspaceName?: string;\n rootAuthToken?: string;\n};\n\n// #endregion\n\n// #region ---------- Users -----------------------------------------------------------------------\n\nconst zManifestUser = z.number().describe(\"User device index\");\nconst zManifestApiUser = z.object({\n name: z.string().describe(\"API user name\"),\n role: z.enum([\"ADMIN\", \"OPERATOR\"]).describe(\"API user role\").default(\"OPERATOR\"),\n pubKey: z.string().describe(\"API user public key\"),\n viewAll: z.boolean().describe(\"Whether the API user can view all accounts\"),\n});\n\nexport type ManifestApiUser = z.infer<typeof zManifestApiUser>;\n\n// #endregion\n\n// #region ---------- Groups ----------------------------------------------------------------------\n\nconst zManifestGroup = z\n .object({\n name: z.string().describe(\"Group name\"),\n members: z.array(zManifestUser).describe(\"Group members\"),\n })\n .strict()\n .describe(\"Operators group\");\n\nexport type ManifestGroup = z.infer<typeof zManifestGroup>;\n\n// #endregion\n\n// #region ---------- Whitelists ------------------------------------------------------------------\n\nconst zManifestWhitelistAddress = z\n .object({\n name: z.string().describe(\"Whitelist address name\"),\n currency: z.string().describe(\"Whitelist address currency\"),\n address: z.string().describe(\"Whitelist address\"),\n destinationTags: z\n .array(z.string())\n .optional()\n .describe(\"List of destination tags (applicable for Ripple currency)\"),\n })\n .strict();\n\nconst zManifestWhitelist = z\n .object({\n name: z.string().describe(\"Whitelist name\"),\n description: z.string().optional().default(\"\").describe(\"Whitelist description\"),\n type: z\n .enum([\"TRANSACTION\", \"SMART_CONTRACT\"])\n .optional()\n .default(\"TRANSACTION\")\n .describe(\"Whitelist type\"),\n addresses: z.array(zManifestWhitelistAddress).describe(\"Whitelist addresses\"),\n })\n .strict()\n .describe(\"Whitelist\");\n\nexport type ManifestWhitelist = z.infer<typeof zManifestWhitelist>;\n\n// #endregion\n\n// #region ---------- Policies --------------------------------------------------------------------\n\nconst zManifestGovernanceStepWithUsers = z\n .object({\n quorum: z.number(),\n members: z.array(zManifestUser),\n })\n .strict();\n\nconst zManifestGovernanceStepWithGroup = z\n .object({\n quorum: z.number(),\n group: z.string(),\n })\n .strict();\n\nconst zManifestGovernanceStep = z.union([\n zManifestGovernanceStepWithUsers,\n zManifestGovernanceStepWithGroup,\n]);\n\nconst zManifestGovernanceRule = z\n .object({\n // TODO see if there is a way to import this from `api` package\n // (the challenge there is that enums are not transpiled)\n type: z.enum([\n \"SEND\",\n \"STAKE\",\n \"DEPLOY_CONTRACT\",\n \"EXECUTE_CONTRACT\",\n \"SIGN_DIGESTS\",\n \"SIGN_MESSAGE\",\n ]),\n steps: z.array(zManifestGovernanceStep).min(1),\n })\n .strict();\n\nexport type ManifestGovernanceRule = z.infer<typeof zManifestGovernanceRule>;\n\nexport const zManifestPolicy = z\n .object({\n name: z.string(),\n currency: z.string(),\n rules: z.array(zManifestGovernanceRule),\n })\n .strict();\n\nexport type ManifestPolicy = z.infer<typeof zManifestPolicy>;\n\n// #endregion\n\n// #region ---------- Accounts --------------------------------------------------------------------\n\nconst zManifestClassicAccountGovernance = z\n .object({\n type: z.literal(\"CLASSIC\"),\n rules: z.array(zManifestGovernanceRule),\n })\n .strict();\n\nconst zManifestTradelinkExchangeConfig = z\n .object({\n name: z.string().describe(\"Exchange name\"),\n repledgeAuthorized: z.boolean().optional().describe(\"Whether repledge is authorized\"),\n needsAssetManagerApprovalForSettlements: z\n .boolean()\n .optional()\n .describe(\"Whether asset manager pre approval is needed\"),\n })\n .strict();\n\nconst zManifestTradelinkAccountGovernance = z\n .object({\n type: z.literal(\"TRADELINK\"),\n assetManager: z.string().describe(\"Asset manager name\"),\n exchanges: z.array(zManifestTradelinkExchangeConfig),\n })\n .strict();\n\nconst zManifestAccountGovernance = z.discriminatedUnion(\"type\", [\n zManifestClassicAccountGovernance,\n zManifestTradelinkAccountGovernance,\n]);\n\nconst zManifestAccount = z\n .object({\n name: z.string(),\n currency: z.string(),\n index: z.number().nonnegative().optional(),\n contractAddress: z.string().optional(),\n governance: zManifestAccountGovernance,\n })\n .strict();\n\nexport type ManifestAccount = z.infer<typeof zManifestAccount>;\n\n// #endregion\n\n// #region ---------- Pledge adjustments (increment/decrement) ------------------------------------\n\nconst zManifestPledgeAdjustment = z\n .object({\n account: z.string(),\n exchange: z.string(),\n amount: z.string(),\n })\n .strict();\n\nexport type ManifestPledgeAdjustment = z.infer<typeof zManifestPledgeAdjustment>;\n\n// #endregion\n\n// #region ---------- Tradelink network -----------------------------------------------------------\n\nconst zManifestTradelinkGroup = z\n .object({\n members: z.array(zManifestUser),\n quorum: z.number(),\n })\n .strict()\n .describe(\"Tradelink group\");\n\nexport type ManifestTradelinkGroup = z.infer<typeof zManifestTradelinkGroup>;\n\nconst zManifestTradelinkGroups = z.array(zManifestTradelinkGroup);\n\nconst zManifestTradelinkWhitelistAddress = z\n .object({\n name: z.string().min(1),\n currency: z.string().min(1),\n address: z.string().min(1),\n })\n .strict()\n .describe(\"Tradelink whitelist address\");\n\nconst zManifestTradelinkWhitelist = z\n .array(zManifestTradelinkWhitelistAddress)\n .describe(\"Tradelink whitelist\");\n\nconst zManifestTradelinkEntity = z\n .object({\n name: z.string(),\n groups: zManifestTradelinkGroups,\n whitelist: zManifestTradelinkWhitelist,\n })\n .strict();\n\nexport type ManifestTradelinkEntity = z.infer<typeof zManifestTradelinkEntity>;\n\nconst zManifestTradelinkCustodian = z\n .object({\n settlement: zManifestTradelinkGroups,\n withdraw: zManifestTradelinkGroups,\n arbitration: zManifestTradelinkGroups,\n })\n .strict();\n\nconst zManifestTradelinkNetworkBlueprint = z\n .object({\n custodian: z.string(),\n exchanges: z.array(z.string()),\n assetManagers: z.array(z.string()),\n })\n .strict();\n\nexport type ManifestTradelinkNetworkBlueprint = z.infer<typeof zManifestTradelinkNetworkBlueprint>;\n\nconst zManifestTradelinkNetwork = z\n .object({\n networkBlueprint: zManifestTradelinkNetworkBlueprint.optional(),\n custodian: zManifestTradelinkCustodian.optional(),\n exchanges: z.array(zManifestTradelinkEntity).optional(),\n assetManagers: z.array(zManifestTradelinkEntity).optional(),\n })\n .strict()\n .describe(\"Tradelink network configuration\");\n\nexport type ManifestTradelinkNetwork = z.infer<typeof zManifestTradelinkNetwork>;\n\n// #endregion\n\n// #region ---------- Workspace -------------------------------------------------------------------\n\nconst zManifestWorkspace = z\n .object({\n tradelink: zManifestTradelinkNetwork.optional(),\n users: z\n .object({\n admins: z.array(zManifestUser).optional(),\n operators: z.array(zManifestUser).optional(),\n api: z.array(zManifestApiUser).optional(),\n })\n .optional(),\n groups: z.array(zManifestGroup).optional(),\n whitelists: z.array(zManifestWhitelist).optional(),\n policies: z.array(zManifestPolicy).optional(),\n accounts: z.array(zManifestAccount).optional(),\n pledges: z.array(zManifestPledgeAdjustment).optional(),\n })\n .strict()\n .describe(\"Workspace configuration\");\n\nexport type ManifestWorkspace = z.infer<typeof zManifestWorkspace>;\n\n// #endregion\n\n// #region ---------- Tradelink organization ------------------------------------------------------\n\nconst zManifestTradelinkOrgEntity = z\n .object({\n name: z.string(),\n code: z.string(),\n logo: z.string(),\n })\n .strict()\n .describe(\"Tradelink organization entity\");\n\nconst zManifestTradelinkOrg = z\n .object({\n exchanges: z.array(zManifestTradelinkOrgEntity).optional(),\n assetManagers: z.array(zManifestTradelinkOrgEntity).optional(),\n custodians: z.array(zManifestTradelinkOrgEntity).optional(),\n })\n .strict()\n .describe(\"Tradelink organization configuration\");\n\nexport type ManifestTradelinkOrg = z.infer<typeof zManifestTradelinkOrg>;\n\n// #endregion\n\n// #region ---------- Manifest --------------------------------------------------------------------\n\nexport const zManifest = z\n .object({\n manifestVersion: z.literal(2),\n tradelink: zManifestTradelinkOrg.optional(),\n workspace: zManifestWorkspace.optional(),\n })\n .strict();\n\nexport type Manifest = z.infer<typeof zManifest>;\n\n// #endregion\n"],"mappings":"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","names":["invariant","invariant","account","invariant","exchange","blueprintExchange","_","invariant","assetManager","invariant","t","c","usersWithDeviceIndex","acc","exchange","invariant"]}
1
+ {"version":3,"sources":["../src/bake/index.ts","../src/bake/bake-pledge.ts","../src/bake/utils.ts","../src/bake/bake-tradelink-organization.ts","../src/bake/bake-workspace.ts","../src/bake/types.ts"],"sourcesContent":["import invariant from \"invariant\";\n\nimport type { Logger } from \"@/types\";\n\nimport { bakePledgeAdjustment } from \"./bake-pledge\";\nimport { bakeTradelinkOrganization } from \"./bake-tradelink-organization\";\nimport { bakeWorkspace } from \"./bake-workspace\";\nimport type { BakeOptions } from \"./types\";\n\nexport * from \"./bake-pledge\";\n\nexport * from \"./types\";\n\nexport { createAndApproveRequest } from \"./utils\";\n\nexport async function bakeManifest(options: BakeOptions, logger: Logger): Promise<void> {\n const {\n engine,\n workspaceName,\n rootAuthToken,\n manifest: { tradelink, workspace },\n } = options;\n\n if (tradelink) {\n invariant(rootAuthToken, `rootAuthToken is required to create Tradelink org entities`);\n await bakeTradelinkOrganization(\n {\n engine,\n tradelink,\n rootAuthToken,\n ...(workspace?.tradelink?.networkBlueprint && workspaceName\n ? { networkBlueprint: { blueprint: workspace.tradelink.networkBlueprint, workspaceName } }\n : {}),\n },\n logger,\n );\n }\n\n if (workspace) {\n invariant(workspaceName, `Can't bake workspace without specifying a workspace name`);\n await bakeWorkspace({ engine, workspace, workspaceName }, logger);\n\n if (workspace.pledges) {\n const engineWithWorkspace = engine.withWorkspace(workspaceName);\n for (const pledgeAdjustment of workspace.pledges) {\n await bakePledgeAdjustment({ engine: engineWithWorkspace, pledgeAdjustment }, logger);\n }\n }\n }\n\n logger.info(\"Successfully baked\");\n}\n","import invariant from \"invariant\";\n\nimport type { Engine, WithWorkspace } from \"@/engine\";\nimport type { Logger } from \"@/types\";\nimport { createDeviceIndexResolver, fetchAll } from \"@/utils\";\n\nimport type { ManifestPledgeAdjustment } from \"./types\";\nimport { createAndApproveRequest } from \"./utils\";\n\ntype Options = {\n engine: Engine<WithWorkspace>;\n pledgeAdjustment: ManifestPledgeAdjustment;\n};\n\nconst flattenApprovers = (groups: { quorum: number; userIds: string[] }[]): string[] => {\n return groups.reduce<string[]>((acc, cur) => {\n acc.push(...cur.userIds.slice(0, cur.quorum));\n return acc;\n }, []);\n};\n\nexport async function bakePledgeAdjustment(options: Options, logger: Logger): Promise<void> {\n const { pledgeAdjustment, engine } = options;\n\n const getDeviceIndex = createDeviceIndexResolver(engine);\n\n logger.info(\"Logging in with admin...\");\n const admin = await engine.withDeviceIndex(4).login();\n\n logger.info(\"Fetching account, tradelink blueprint and network...\");\n const [matchingAccounts, blueprint, network] = await Promise.all([\n fetchAll(admin.client.accounts.list.query, { name: pledgeAdjustment.account }),\n admin.client.tradelink.getNetworkBlueprint.query(),\n admin.client.tradelink.getNetwork.query(),\n ]);\n\n const account = matchingAccounts.find((account) => account.name === pledgeAdjustment.account);\n invariant(account, `Account ${pledgeAdjustment.account} not found`);\n\n invariant(blueprint, \"Tradelink blueprint is not created yet\");\n invariant(network, \"Tradelink network is not created yet\");\n\n const exchange = network.exchanges.find((exchange) => {\n const blueprintExchange = blueprint.exchanges.find(\n (blueprintExchange) => blueprintExchange.tradelinkId === exchange.tradelinkId,\n );\n invariant(blueprintExchange, `Exchange ${exchange.tradelinkId} not found in blueprint`);\n return blueprintExchange.name === pledgeAdjustment.exchange;\n });\n invariant(exchange, `Exchange ${pledgeAdjustment.exchange} not found in network`);\n\n const governance = account.governance;\n invariant(governance.type === \"TRADELINK\", \"Account governance is not TRADELINK\");\n const assetManager = network.assetManagers.find((am) => am.id === governance.assetManagerId);\n invariant(assetManager, `Asset manager ${governance.assetManagerId} not found in network`);\n\n const exchangeIsConfiguredForAccount = !!governance.exchangeConfigs.find(\n (e) => e.exchangeId === exchange.id,\n );\n invariant(\n exchangeIsConfiguredForAccount,\n `Exchange ${exchange.id} is not configured for account ${account.id}`,\n );\n\n const approverIds = [\n ...flattenApprovers(assetManager.groups),\n ...flattenApprovers(exchange.groups),\n ];\n\n const approvers = await Promise.all(\n approverIds.map((id) =>\n admin.client.users.findById\n .query({ id })\n .then((user) => getDeviceIndex(user.deviceUserId!))\n .then((index) => engine.withDeviceIndex(index).login()),\n ),\n );\n\n await createAndApproveRequest(\n {\n type: \"ADJUST_PLEDGE\",\n data: {\n accountId: account.id,\n exchangeId: exchange.id,\n amount: pledgeAdjustment.amount,\n },\n },\n approvers,\n logger,\n );\n\n logger.info(\n `Successfully adjusted pledge for account ${pledgeAdjustment.account} on exchange ${pledgeAdjustment.exchange}`,\n );\n}\n","import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { Engine, WithDevice, WithPsdAuth, WithWorkspace } from \"@/engine\";\nimport type { RouterInputs } from \"@/trpc\";\nimport type { Logger } from \"@/types\";\n\ntype LogFunction = (msg: string) => void;\n\ntype LogHelpers = {\n logTitle: LogFunction;\n logStep: LogFunction;\n logSubStep: LogFunction;\n};\n\nexport function createBakeLogHelpers(logger: Logger): LogHelpers {\n return {\n logTitle(title: string): void {\n logger.info(`:: ${title} ::`);\n },\n logStep(msg: string): void {\n logger.info(`=> ${msg}`);\n },\n logSubStep(msg: string): void {\n logger.info(` -> ${msg}`);\n },\n };\n}\n\nexport type CreateRequestInput = RouterInputs[\"requests\"][\"create\"][\"request\"];\n\nexport type inferRequestInputData<T extends RouterInputs[\"requests\"][\"create\"][\"request\"][\"type\"]> =\n Extract<RouterInputs[\"requests\"][\"create\"][\"request\"], { type: T }>[\"data\"];\n\nexport async function approveRequest(\n request: VaultRequestResponse,\n approvers: Engine<WithWorkspace & WithDevice & WithPsdAuth>[],\n logger: Logger,\n): Promise<VaultRequestResponse> {\n const { logSubStep } = createBakeLogHelpers(logger);\n for (let i = 0; i < approvers.length; i++) {\n logSubStep(`Collecting approval (${i + 1}/${approvers.length})...`);\n const approver = approvers[i]!;\n request = await approver.approve(request);\n }\n return request;\n}\n\nexport async function createAndApproveRequest(\n input: CreateRequestInput,\n approvers: Engine<WithWorkspace & WithDevice & WithPsdAuth>[],\n logger: Logger,\n): Promise<VaultRequestResponse> {\n const { logSubStep } = createBakeLogHelpers(logger);\n const creator = approvers[0];\n invariant(creator, \"Need at least 1 user to create a request\");\n logSubStep(`Creating request of type ${input.type}...`);\n const request = await creator.client.requests.create.mutate({ request: input });\n return approveRequest(request, approvers, logger);\n}\n","import type { Logger } from \"@/types\";\n\nimport type { BakeOptions, ManifestTradelinkNetworkBlueprint, ManifestTradelinkOrg } from \"./types\";\nimport { createBakeLogHelpers } from \"./utils\";\n\ntype Options = Omit<BakeOptions, \"manifest\" | \"rootAuthToken\"> & {\n tradelink: ManifestTradelinkOrg;\n rootAuthToken: string;\n networkBlueprint?: { workspaceName: string; blueprint: ManifestTradelinkNetworkBlueprint };\n};\n\nexport async function bakeTradelinkOrganization(options: Options, logger: Logger): Promise<void> {\n const { tradelink, engine, rootAuthToken, networkBlueprint } = options;\n\n const { logStep } = createBakeLogHelpers(logger);\n\n const rootClient = engine.createClient({ rootAuthToken });\n if (tradelink.exchanges) {\n logStep(\"Creating Tradelink organization exchanges...\");\n const existingOrgExchanges = await rootClient.tradelink.root.listOrgExchanges.query();\n for (const orgExchange of tradelink.exchanges) {\n const existingOrgExchange = existingOrgExchanges.find((e) => e.name === orgExchange.name);\n if (existingOrgExchange) {\n logger.info(\n `[SKIPPED] Organization exchange ${existingOrgExchange.name} (${existingOrgExchange.code}) already exists`,\n );\n } else {\n await rootClient.tradelink.root.createOrgExchange.mutate({\n code: orgExchange.code,\n name: orgExchange.name,\n logoUrl: orgExchange.logo,\n });\n logger.info(`Created organization exchange ${orgExchange.name} (${orgExchange.code})`);\n }\n }\n }\n if (tradelink.assetManagers) {\n logStep(\"Creating Tradelink organization asset managers...\");\n const existingAssetManagers = await rootClient.tradelink.root.listOrgAssetManagers.query();\n for (const orgAssetManager of tradelink.assetManagers) {\n const existingOrgAssetManager = existingAssetManagers.find(\n (e) => e.name === orgAssetManager.name,\n );\n if (existingOrgAssetManager) {\n logger.info(\n `[SKIPPED] Organization asset manager ${existingOrgAssetManager.name} (${existingOrgAssetManager.code}) already exists`,\n );\n } else {\n await rootClient.tradelink.root.createOrgAssetManager.mutate({\n code: orgAssetManager.code,\n name: orgAssetManager.name,\n logoUrl: orgAssetManager.logo,\n });\n logger.info(\n `Created organization asset manager ${orgAssetManager.name} (${orgAssetManager.code})`,\n );\n }\n }\n }\n if (tradelink.custodians) {\n logStep(\"Creating Tradelink organization custodians...\");\n const existingCustodians = await rootClient.tradelink.root.listOrgCustodians.query();\n for (const orgCustodian of tradelink.custodians) {\n const existingOrgCustodian = existingCustodians.find((e) => e.name === orgCustodian.name);\n if (existingOrgCustodian) {\n logger.info(\n `[SKIPPED] Organization custodian ${existingOrgCustodian.name} (${existingOrgCustodian.code}) already exists`,\n );\n } else {\n await rootClient.tradelink.root.createOrgCustodian.mutate({\n code: orgCustodian.code,\n name: orgCustodian.name,\n logoUrl: orgCustodian.logo,\n });\n logger.info(`Created organization custodian ${orgCustodian.name} (${orgCustodian.code})`);\n }\n }\n }\n if (networkBlueprint) {\n logStep(\"Creating Tradelink network blueprint...\");\n const { workspaceName, blueprint } = networkBlueprint;\n const existingBlueprints = await rootClient.tradelink.root.listNetworkBlueprints.query();\n const existingBlueprint = existingBlueprints.find((e) => e.workspaceName === workspaceName);\n if (existingBlueprint) {\n logger.info(`[SKIPPED] Network blueprint for ${workspaceName} workspace already exists`);\n } else {\n await rootClient.tradelink.root.createNetworkBlueprint.mutate({\n workspaceName,\n custodian: { name: blueprint.custodian },\n exchanges: blueprint.exchanges.map((_) => ({ name: _ })),\n assetManagers: blueprint.assetManagers.map((_) => ({ name: _ })),\n });\n logger.info(`Created network blueprint for ${networkBlueprint.workspaceName} workspace`);\n }\n }\n}\n","import type {\n ReviewStepWithUsers,\n TradelinkNetworkBlueprintResponse,\n UserResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport _ from \"lodash\";\n\nimport type { Logger } from \"@/types\";\nimport { createDeviceIndexResolver, fetchAll } from \"@/utils\";\n\nimport type {\n BakeOptions,\n ManifestAccount,\n ManifestApiUser,\n ManifestGovernanceRule,\n ManifestGroup,\n ManifestPolicy,\n ManifestTradelinkEntity,\n ManifestTradelinkGroup,\n ManifestTradelinkNetwork,\n ManifestWhitelist,\n ManifestWorkspace,\n} from \"./types\";\nimport {\n type CreateRequestInput,\n approveRequest,\n createAndApproveRequest,\n createBakeLogHelpers,\n type inferRequestInputData,\n} from \"./utils\";\n\ntype GovRuleData = inferRequestInputData<\"CREATE_POLICY\">[\"govRules\"][number];\n\ntype Options = Omit<BakeOptions, \"manifest\" | \"workspaceName\"> & {\n workspace: ManifestWorkspace;\n workspaceName: string;\n};\n\nexport async function bakeWorkspace(options: Options, logger: Logger): Promise<void> {\n const { workspace, engine, workspaceName } = options;\n\n const workspaceEngine = engine.withWorkspace(workspaceName);\n const { logTitle, logStep, logSubStep } = createBakeLogHelpers(logger);\n\n // utility to retrieve device index based on device user id\n const findDeviceIndex = createDeviceIndexResolver(workspaceEngine);\n\n // Log-in once with the two admins (index 4 & 5 by convention) that will create all\n // the requests for the manifest objects.\n logger.info(\"Authenticating with two admins...\");\n const [admin1, admin2] = await Promise.all([\n workspaceEngine.withDeviceIndex(4).login(),\n workspaceEngine.withDeviceIndex(5).login(),\n ]);\n\n // Retrieve all existing data, so we are then able to skip creating stuff when not needed.\n logger.info(\"Fetching existing data...\");\n const [\n existingUsers,\n existingGroups,\n existingPolicies,\n existingAccounts,\n tradelinkNetworkBlueprint,\n ] = await Promise.all([\n fetchAll(admin1.client.users.list.query, { status: \"ACTIVE\" }),\n fetchAll(admin1.client.groups.list.query, { status: \"ACTIVE\" }),\n fetchAll(admin1.client.policies.list.query, { isPrivate: false }),\n fetchAll(admin1.client.accounts.list.query, { status: \"ACTIVE\", skipLiveData: true }),\n admin1.client.tradelink.getNetworkBlueprint.query(),\n ]);\n\n const tradelinkOrgExchangesByName = _.keyBy(tradelinkNetworkBlueprint?.exchanges, \"name\");\n const tradelinkOrgAssetManagersByName = _.keyBy(tradelinkNetworkBlueprint?.assetManagers, \"name\");\n\n let existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n\n // Merge admins & operators (we can't fetch all users in a row because we don't want API users,\n // and we don't have a way to retrieve both admins & operators in a single fetch)\n const existingPsdUsers = existingUsers.filter((user) => user.deviceType === \"PSD\");\n const existingApiUsers = existingUsers.filter((user) => user.deviceType === \"API\");\n // Retrieve all device indexes for the existing users\n const usersWithDeviceIndex = await resolveDevicesIndexes(existingPsdUsers);\n\n // ---------------------------------\n // USERS\n // ---------------------------------\n if (workspace.users) {\n logTitle(\"Users\");\n if (workspace.users.admins) {\n for (const deviceIndex of workspace.users.admins) {\n await createUser(\"ADMIN\", deviceIndex);\n }\n }\n if (workspace.users.operators) {\n for (const deviceIndex of workspace.users.operators) {\n await createUser(\"OPERATOR\", deviceIndex);\n }\n }\n if (workspace.users.api) {\n for (const apiUser of workspace.users.api) {\n await createApiUser(apiUser);\n }\n }\n }\n\n // ---------------------------------\n // GROUPS\n // ---------------------------------\n if (workspace.groups) {\n logTitle(\"Groups\");\n for (const group of workspace.groups) {\n await createGroup(group);\n }\n }\n\n // ---------------------------------\n // WHITELISTS\n // ---------------------------------\n if (workspace.whitelists) {\n logTitle(\"Whitelists\");\n await createWhitelists(workspace.whitelists);\n }\n\n // POLICIES\n // ---------------------------------\n if (workspace.policies) {\n logTitle(\"Policies\");\n for (const policy of workspace.policies) {\n await createPolicy(policy);\n }\n }\n\n // ---------------------------------\n // TRADELINK NETWORK\n // ---------------------------------\n if (workspace.tradelink) {\n logTitle(\"Tradelink\");\n await createTradelink(workspace.tradelink);\n }\n\n // ---------------------------------\n // ACCOUNTS\n // ---------------------------------\n if (workspace.accounts) {\n logTitle(\"Accounts\");\n for (const account of workspace.accounts) {\n await createAccount(account);\n }\n }\n\n async function createWhitelists(whitelists: ManifestWhitelist[]): Promise<void> {\n const existingWhitelists = await fetchAll(admin1.client.whitelists.list.query, {\n status: \"ACTIVE\",\n });\n for (const whitelist of whitelists) {\n await createWhitelist(whitelist);\n }\n\n async function createWhitelist(whitelist: ManifestWhitelist): Promise<void> {\n const existing = existingWhitelists.find((w) => w.name === whitelist.name);\n\n // TODO: compare with existing to eventually do an EDIT\n if (existing) {\n logger.info(`[SKIPPED] Whitelist \"${whitelist.name}\" already exists`);\n return;\n }\n\n const input: CreateRequestInput = {\n type: \"CREATE_WHITELIST\",\n data: whitelist,\n };\n\n await createAndApproveRequest(input, [admin1, admin2], logger);\n logSubStep(`Whitelist \"${whitelist.name}\" has been created`);\n }\n }\n\n function govRuleFromManifest(rule: ManifestGovernanceRule): GovRuleData {\n return {\n operationType: rule.type,\n reviewSteps: rule.steps.map((step) => {\n if (\"group\" in step) {\n return {\n quorum: step.quorum,\n groupId: groupIdFromName(step.group),\n };\n }\n return {\n quorum: step.quorum,\n userIds: step.members.map(userIdFromDeviceIndex),\n };\n }),\n };\n }\n\n async function createAccount(account: ManifestAccount): Promise<void> {\n const existing = existingAccounts.find((a) => a.name === account.name);\n if (existing) {\n logger.info(`[SKIPPED] Account \"${account.name}\" already exists`);\n return;\n }\n logStep(`Creating account \"${account.name}\"`);\n const input: CreateRequestInput = {\n type: \"CREATE_ACCOUNT\",\n data: {\n // general fields\n name: account.name,\n currency: account.currency,\n contractAddress: account.contractAddress,\n index: account.index,\n\n // governance fields\n governance:\n account.governance.type === \"TRADELINK\"\n ? {\n type: \"TRADELINK\",\n assetManagerId: assetManagerIdFromName(account.governance.assetManager),\n exchangeConfigs: account.governance.exchanges.map((exchangeConfig) => ({\n exchangeId: exchangeIdFromName(exchangeConfig.name),\n repledgeAuthorized: exchangeConfig.repledgeAuthorized === true,\n needsAssetManagerApprovalForSettlements:\n exchangeConfig.needsAssetManagerApprovalForSettlements === true,\n })),\n }\n : {\n type: \"CLASSIC\",\n policy: { rules: account.governance.rules.map(govRuleFromManifest) },\n },\n },\n };\n\n const req = await createAndApproveRequest(input, [admin1, admin2], logger);\n\n if (account.governance.type === \"TRADELINK\") {\n logStep(`Activating tradelink account \"${account.name}\"`);\n // we need to activate the account with the asset manager\n const assetManagerId = assetManagerIdFromName(account.governance.assetManager);\n const assetManager = existingTradelinkNetwork?.assetManagers.find(\n (assetManager) => assetManager.id === assetManagerId,\n );\n invariant(assetManager, `Asset manager for account exists`);\n const loggedAssetManagerOperators = await Promise.all(\n assetManager.groups.flatMap(({ quorum, userIds }) =>\n userIds.slice(0, quorum).map((userId) => {\n const deviceIndex = usersWithDeviceIndex.find((o) => o.user.id === userId)?.deviceIndex;\n return workspaceEngine.withDeviceIndex(deviceIndex!).login();\n }),\n ),\n );\n await createAndApproveRequest(\n { type: \"ACTIVATE_TRADELINK_ACCOUNT\", targetId: req.targetId!, data: {} },\n loggedAssetManagerOperators,\n logger,\n );\n }\n\n logSubStep(`Account ${account.name} has been created`);\n }\n\n async function createUser(role: \"ADMIN\" | \"OPERATOR\", deviceIndex: number): Promise<void> {\n const userEngine = workspaceEngine.withDeviceIndex(deviceIndex);\n const deviceId = await userEngine.device.getDeviceUserId();\n\n // eventually check if we can skip user creation\n const existing = existingUsers.find((user) => user.deviceUserId === deviceId);\n if (existing) {\n logger.info(`[SKIPPED] User with device index ${deviceIndex} already exists`);\n return;\n }\n\n const name = `${role === \"ADMIN\" ? \"Admin\" : \"Operator\"} ${deviceIndex}`;\n logStep(`Creating ${name}`);\n\n logSubStep(\"Creating invitation...\");\n let registration = await admin1.client.userRegistrations.invite.mutate({\n name,\n role,\n deviceUserId: deviceId,\n psdModel: \"STAX\",\n });\n\n logSubStep(\"Completing registration...\");\n registration = await userEngine.register(registration);\n\n logSubStep(\"Creating request...\");\n let req = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_PSD_USER\",\n data: { registrationId: registration.id },\n },\n });\n\n req = await approveRequest(req, [admin1, admin2], logger);\n logSubStep(`${name} has been created`);\n\n const createdUser = await admin1.client.users.findById.query({ id: req.targetId! });\n\n // patch the current state with the newly created user\n existingUsers.push(createdUser);\n usersWithDeviceIndex.push({ user: createdUser, deviceIndex });\n }\n\n async function createApiUser(apiUser: ManifestApiUser): Promise<void> {\n const existing = existingApiUsers.find(\n (user) => user.pubKey === apiUser.pubKey || user.name === apiUser.name,\n );\n if (existing) {\n logger.info(\n `[SKIPPED] API user already exists with name \"${apiUser.name}\" or public key \"${apiUser.pubKey}\"`,\n );\n return;\n }\n\n logStep(`Creating API user \"${apiUser.name}\"...`);\n\n logSubStep(\"Creating request...\");\n let req = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_API_USER\",\n data: {\n name: apiUser.name,\n role: apiUser.role,\n pubKey: apiUser.pubKey,\n viewAll: apiUser.viewAll,\n },\n },\n });\n req = await approveRequest(req, [admin1, admin2], logger);\n logSubStep(`API user \"${apiUser.name}\" has been created`);\n\n logSubStep(\"Generating credentials...\");\n const credentials = await admin1.client.users.resetApiUserCredentials.mutate({\n id: req.targetId!,\n });\n logSubStep(\n `API user \"${apiUser.name}\" credentials have been generated: apiKeyId=${credentials.apiKeyId}, apiKeySecret=${credentials.apiKeySecret}`,\n );\n const createdUser = await admin1.client.users.findById.query({ id: req.targetId! });\n // patch the current state with the newly created user\n existingApiUsers.push(createdUser);\n }\n\n async function createGroup(group: ManifestGroup): Promise<void> {\n const existing = existingGroups.find((g) => g.name === group.name);\n if (existing) {\n logger.info(`[SKIPPED] Group \"${group.name}\" already exists`);\n return;\n }\n\n logStep(`Creating group ${group.name}...`);\n\n const members = group.members.map(userIdFromDeviceIndex);\n\n logSubStep(\"Creating request...\");\n let request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_GROUP\",\n data: {\n name: group.name,\n description: \"\",\n members,\n },\n },\n });\n\n request = await approveRequest(request, [admin1, admin2], logger);\n logSubStep(`${group.name} has been created`);\n\n const createdGroup = await admin1.client.groups.findById.query({ id: request.targetId! });\n existingGroups.push(createdGroup);\n }\n\n async function createPolicy(policy: ManifestPolicy): Promise<void> {\n const existing = existingPolicies.find((p) => p.name === policy.name);\n if (existing) {\n logger.info(`[SKIPPED] Policy \"${policy.name}\" already exists`);\n return;\n }\n\n logStep(`Creating policy ${policy.name}...`);\n\n logSubStep(\"Creating request...\");\n let request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_POLICY\",\n data: {\n name: policy.name,\n currency: policy.currency,\n description: \"\",\n govRules: policy.rules.map(govRuleFromManifest),\n },\n },\n });\n\n request = await approveRequest(request, [admin1, admin2], logger);\n logSubStep(`${policy.name} has been created`);\n\n const createdPolicy = await admin1.client.policies.findById.query({ id: request.targetId! });\n existingPolicies.push(createdPolicy);\n }\n\n async function createTradelink(tradelink: ManifestTradelinkNetwork): Promise<void> {\n if (tradelink.custodian) {\n if (existingTradelinkNetwork === null) {\n logStep(\"Creating custodian config...\");\n const { settlement, withdraw, arbitration } = tradelink.custodian;\n const data = {\n settlement: settlement.map(tradelinkReviewStepFromManifest),\n withdraw: withdraw.map(tradelinkReviewStepFromManifest),\n arbitration: arbitration.map(tradelinkReviewStepFromManifest),\n };\n\n logSubStep(\"Creating request...\");\n const request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_TRADELINK_CUSTODIAN\",\n data,\n },\n });\n\n await approveRequest(request, [admin1, admin2], logger);\n logSubStep(\"Tradelink custodian config has been created\");\n\n existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n } else {\n logger.info(\"[SKIPPED] Custodian config already exists\");\n }\n\n const networkBlueprint = await admin1.client.tradelink.getNetworkBlueprint.query();\n if (networkBlueprint !== null) {\n if (tradelink.exchanges !== undefined) {\n await createTradelinkExchanges(networkBlueprint, tradelink.exchanges);\n }\n\n if (tradelink.assetManagers !== undefined) {\n await createTradelinkAssetManagers(networkBlueprint, tradelink.assetManagers);\n }\n } else {\n logger.error(\n \"Will not create exchanges and asset managers because there is no network blueprint for current workspace\",\n );\n }\n }\n }\n\n async function createTradelinkExchanges(\n networkBlueprint: TradelinkNetworkBlueprintResponse,\n exchanges: ManifestTradelinkEntity[],\n ): Promise<void> {\n invariant(existingTradelinkNetwork !== null, \"Network should exist\");\n const blueprintExchanges = networkBlueprint.exchanges;\n for (const exchange of exchanges) {\n // find uid\n const blueprintExchange = blueprintExchanges.find(({ name }) => name === exchange.name);\n invariant(\n blueprintExchange !== undefined,\n `Exchange ${exchange.name} does not exist in network blueprint`,\n );\n const exchangeId = blueprintExchange.tradelinkId;\n logStep(`Creating exchange ${exchange.name}...`);\n if (\n existingTradelinkNetwork.exchanges.find(({ tradelinkId }) => tradelinkId === exchangeId) !==\n undefined\n ) {\n logger.info(`[SKIPPED] Exchange \"${exchange.name}\" already exists`);\n continue;\n }\n\n logSubStep(\"Creating request...\");\n const request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_TRADELINK_EXCHANGE\",\n data: {\n tradelinkId: exchangeId,\n groups: exchange.groups.map(tradelinkReviewStepFromManifest),\n whitelist: exchange.whitelist,\n },\n },\n });\n\n const loggedExchangeOperators = await Promise.all(\n exchange.groups.flatMap(({ quorum, members }) =>\n members\n .slice(0, quorum)\n .map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login()),\n ),\n );\n\n await approveRequest(request, [admin1, admin2, ...loggedExchangeOperators], logger);\n\n // refresh tradelink network\n existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n invariant(existingTradelinkNetwork !== null, \"Tradelink network exists\");\n }\n }\n\n async function createTradelinkAssetManagers(\n networkBlueprint: TradelinkNetworkBlueprintResponse,\n assetManagers: ManifestTradelinkEntity[],\n ): Promise<void> {\n invariant(existingTradelinkNetwork !== null, \"Network should exist\");\n const blueprintAssetManagers = networkBlueprint.assetManagers;\n for (const assetManager of assetManagers) {\n // find uid\n const blueprintAssetManager = blueprintAssetManagers.find(\n ({ name }) => name === assetManager.name,\n );\n invariant(\n blueprintAssetManager !== undefined,\n `AssetManager ${assetManager.name} does not exist in network blueprint`,\n );\n const assetManagerId = blueprintAssetManager.tradelinkId;\n logStep(`Creating assetManager ${assetManager.name}...`);\n if (\n existingTradelinkNetwork.assetManagers.find(\n ({ tradelinkId }) => tradelinkId === assetManagerId,\n ) !== undefined\n ) {\n logger.info(`[SKIPPED] Asset manager \"${assetManager.name}\" already exists`);\n continue;\n }\n\n logSubStep(\"Creating request...\");\n const request = await admin1.client.requests.create.mutate({\n request: {\n type: \"CREATE_TRADELINK_ASSET_MANAGER\",\n data: {\n tradelinkId: assetManagerId,\n groups: assetManager.groups.map(tradelinkReviewStepFromManifest),\n whitelist: assetManager.whitelist,\n },\n },\n });\n\n const loggedAssetManagerOperators = await Promise.all(\n assetManager.groups.flatMap(({ quorum, members }) =>\n members\n .slice(0, quorum)\n .map((deviceIndex) => workspaceEngine.withDeviceIndex(deviceIndex).login()),\n ),\n );\n\n await approveRequest(request, [admin1, admin2, ...loggedAssetManagerOperators], logger);\n\n // refresh tradelink network\n existingTradelinkNetwork = await admin1.client.tradelink.getNetwork.query();\n invariant(existingTradelinkNetwork !== null, \"Tradelink network exists\");\n }\n }\n\n // For each given user, retrieve (by brute force) their device index, by comparing their\n // device user id with the one computed for each tested index.\n // Using .reduce() here to leverage caching existing discoveries\n async function resolveDevicesIndexes(\n users: UserResponse[],\n ): Promise<{ user: UserResponse; deviceIndex: number }[]> {\n const usersWithDeviceIndex = await users.reduce<\n Promise<{ user: UserResponse; deviceIndex: number }[]>\n >(\n (acc, cur) =>\n acc.then(async (acc) => {\n acc.push(await withDeviceIndex(cur));\n return acc;\n }),\n Promise.resolve([]),\n );\n return usersWithDeviceIndex;\n }\n\n async function withDeviceIndex(\n user: UserResponse,\n ): Promise<{ user: UserResponse; deviceIndex: number }> {\n invariant(user.deviceUserId, `User ${user.id} does not have any device user id`);\n const deviceIndex = await findDeviceIndex(user.deviceUserId);\n return { user, deviceIndex };\n }\n\n function userIdFromDeviceIndex(deviceIndex: number): string {\n const corresponding = usersWithDeviceIndex.find((o) => o.deviceIndex === deviceIndex);\n invariant(corresponding, `No user with device index ${deviceIndex}`);\n return corresponding.user.id;\n }\n\n function groupIdFromName(groupName: string): string {\n const group = existingGroups.find((g) => g.name === groupName);\n invariant(group, `Group ${groupName} not found`);\n return group.id;\n }\n\n function assetManagerIdFromName(assetManagerName: string): string {\n const orgAssetManager = tradelinkOrgAssetManagersByName[assetManagerName];\n invariant(\n orgAssetManager,\n `Can't find Tradelink organization asset manager ${assetManagerName}`,\n );\n const assetManager = existingTradelinkNetwork?.assetManagers.find(\n (assetManager) => assetManager.tradelinkId === orgAssetManager.tradelinkId,\n );\n invariant(assetManager, `Can't find Tradelink assetManager ${assetManagerName}`);\n return assetManager.id;\n }\n\n function exchangeIdFromName(exchangeName: string): string {\n const exchange = existingTradelinkNetwork?.exchanges.find((exchange) => {\n const orgExchange = tradelinkOrgExchangesByName[exchangeName];\n invariant(orgExchange, `Can't find Tradelink organization exchange ${exchange.tradelinkId}`);\n return orgExchange.name === exchangeName;\n });\n invariant(exchange, `Can't find Tradelink exchange ${exchangeName}`);\n return exchange.id;\n }\n\n function tradelinkReviewStepFromManifest({\n members,\n quorum,\n }: ManifestTradelinkGroup): ReviewStepWithUsers {\n return {\n userIds: members.map(userIdFromDeviceIndex),\n quorum,\n };\n }\n}\n","import z from \"zod\";\n\nimport type { Engine } from \"@/engine\";\n\n// #region ---------- General types ---------------------------------------------------------------\n\nexport type BakeOptions = {\n manifest: Manifest;\n engine: Engine;\n workspaceName?: string;\n rootAuthToken?: string;\n};\n\n// #endregion\n\n// #region ---------- Users -----------------------------------------------------------------------\n\nconst zManifestUser = z.number().describe(\"User device index\");\nconst zManifestApiUser = z.object({\n name: z.string().describe(\"API user name\"),\n role: z.enum([\"ADMIN\", \"OPERATOR\"]).describe(\"API user role\").default(\"OPERATOR\"),\n pubKey: z.string().describe(\"API user public key\"),\n viewAll: z.boolean().describe(\"Whether the API user can view all accounts\"),\n});\n\nexport type ManifestApiUser = z.infer<typeof zManifestApiUser>;\n\n// #endregion\n\n// #region ---------- Groups ----------------------------------------------------------------------\n\nconst zManifestGroup = z\n .object({\n name: z.string().describe(\"Group name\"),\n members: z.array(zManifestUser).describe(\"Group members\"),\n })\n .strict()\n .describe(\"Operators group\");\n\nexport type ManifestGroup = z.infer<typeof zManifestGroup>;\n\n// #endregion\n\n// #region ---------- Whitelists ------------------------------------------------------------------\n\nconst zManifestWhitelistAddress = z\n .object({\n name: z.string().describe(\"Whitelist address name\"),\n currency: z.string().describe(\"Whitelist address currency\"),\n address: z.string().describe(\"Whitelist address\"),\n destinationTags: z\n .array(z.string())\n .optional()\n .describe(\"List of destination tags (applicable for Ripple currency)\"),\n })\n .strict();\n\nconst zManifestWhitelist = z\n .object({\n name: z.string().describe(\"Whitelist name\"),\n description: z.string().optional().default(\"\").describe(\"Whitelist description\"),\n type: z\n .enum([\"TRANSACTION\", \"SMART_CONTRACT\"])\n .optional()\n .default(\"TRANSACTION\")\n .describe(\"Whitelist type\"),\n addresses: z.array(zManifestWhitelistAddress).describe(\"Whitelist addresses\"),\n })\n .strict()\n .describe(\"Whitelist\");\n\nexport type ManifestWhitelist = z.infer<typeof zManifestWhitelist>;\n\n// #endregion\n\n// #region ---------- Policies --------------------------------------------------------------------\n\nconst zManifestGovernanceStepWithUsers = z\n .object({\n quorum: z.number(),\n members: z.array(zManifestUser),\n })\n .strict();\n\nconst zManifestGovernanceStepWithGroup = z\n .object({\n quorum: z.number(),\n group: z.string(),\n })\n .strict();\n\nconst zManifestGovernanceStep = z.union([\n zManifestGovernanceStepWithUsers,\n zManifestGovernanceStepWithGroup,\n]);\n\nconst zManifestGovernanceRule = z\n .object({\n // TODO see if there is a way to import this from `api` package\n // (the challenge there is that enums are not transpiled)\n type: z.enum([\"SEND\", \"STAKE\", \"DEPLOY_CONTRACT\", \"EXECUTE_CONTRACT\", \"SIGN_MESSAGE\"]),\n steps: z.array(zManifestGovernanceStep).min(1),\n })\n .strict();\n\nexport type ManifestGovernanceRule = z.infer<typeof zManifestGovernanceRule>;\n\nexport const zManifestPolicy = z\n .object({\n name: z.string(),\n currency: z.string(),\n rules: z.array(zManifestGovernanceRule),\n })\n .strict();\n\nexport type ManifestPolicy = z.infer<typeof zManifestPolicy>;\n\n// #endregion\n\n// #region ---------- Accounts --------------------------------------------------------------------\n\nconst zManifestClassicAccountGovernance = z\n .object({\n type: z.literal(\"CLASSIC\"),\n rules: z.array(zManifestGovernanceRule),\n })\n .strict();\n\nconst zManifestTradelinkExchangeConfig = z\n .object({\n name: z.string().describe(\"Exchange name\"),\n repledgeAuthorized: z.boolean().optional().describe(\"Whether repledge is authorized\"),\n needsAssetManagerApprovalForSettlements: z\n .boolean()\n .optional()\n .describe(\"Whether asset manager pre approval is needed\"),\n })\n .strict();\n\nconst zManifestTradelinkAccountGovernance = z\n .object({\n type: z.literal(\"TRADELINK\"),\n assetManager: z.string().describe(\"Asset manager name\"),\n exchanges: z.array(zManifestTradelinkExchangeConfig),\n })\n .strict();\n\nconst zManifestAccountGovernance = z.discriminatedUnion(\"type\", [\n zManifestClassicAccountGovernance,\n zManifestTradelinkAccountGovernance,\n]);\n\nconst zManifestAccount = z\n .object({\n name: z.string(),\n currency: z.string(),\n index: z.number().nonnegative().optional(),\n contractAddress: z.string().optional(),\n governance: zManifestAccountGovernance,\n })\n .strict();\n\nexport type ManifestAccount = z.infer<typeof zManifestAccount>;\n\n// #endregion\n\n// #region ---------- Pledge adjustments (increment/decrement) ------------------------------------\n\nconst zManifestPledgeAdjustment = z\n .object({\n account: z.string(),\n exchange: z.string(),\n amount: z.string(),\n })\n .strict();\n\nexport type ManifestPledgeAdjustment = z.infer<typeof zManifestPledgeAdjustment>;\n\n// #endregion\n\n// #region ---------- Tradelink network -----------------------------------------------------------\n\nconst zManifestTradelinkGroup = z\n .object({\n members: z.array(zManifestUser),\n quorum: z.number(),\n })\n .strict()\n .describe(\"Tradelink group\");\n\nexport type ManifestTradelinkGroup = z.infer<typeof zManifestTradelinkGroup>;\n\nconst zManifestTradelinkGroups = z.array(zManifestTradelinkGroup);\n\nconst zManifestTradelinkWhitelistAddress = z\n .object({\n name: z.string().min(1),\n currency: z.string().min(1),\n address: z.string().min(1),\n })\n .strict()\n .describe(\"Tradelink whitelist address\");\n\nconst zManifestTradelinkWhitelist = z\n .array(zManifestTradelinkWhitelistAddress)\n .describe(\"Tradelink whitelist\");\n\nconst zManifestTradelinkEntity = z\n .object({\n name: z.string(),\n groups: zManifestTradelinkGroups,\n whitelist: zManifestTradelinkWhitelist,\n })\n .strict();\n\nexport type ManifestTradelinkEntity = z.infer<typeof zManifestTradelinkEntity>;\n\nconst zManifestTradelinkCustodian = z\n .object({\n settlement: zManifestTradelinkGroups,\n withdraw: zManifestTradelinkGroups,\n arbitration: zManifestTradelinkGroups,\n })\n .strict();\n\nconst zManifestTradelinkNetworkBlueprint = z\n .object({\n custodian: z.string(),\n exchanges: z.array(z.string()),\n assetManagers: z.array(z.string()),\n })\n .strict();\n\nexport type ManifestTradelinkNetworkBlueprint = z.infer<typeof zManifestTradelinkNetworkBlueprint>;\n\nconst zManifestTradelinkNetwork = z\n .object({\n networkBlueprint: zManifestTradelinkNetworkBlueprint.optional(),\n custodian: zManifestTradelinkCustodian.optional(),\n exchanges: z.array(zManifestTradelinkEntity).optional(),\n assetManagers: z.array(zManifestTradelinkEntity).optional(),\n })\n .strict()\n .describe(\"Tradelink network configuration\");\n\nexport type ManifestTradelinkNetwork = z.infer<typeof zManifestTradelinkNetwork>;\n\n// #endregion\n\n// #region ---------- Workspace -------------------------------------------------------------------\n\nconst zManifestWorkspace = z\n .object({\n tradelink: zManifestTradelinkNetwork.optional(),\n users: z\n .object({\n admins: z.array(zManifestUser).optional(),\n operators: z.array(zManifestUser).optional(),\n api: z.array(zManifestApiUser).optional(),\n })\n .optional(),\n groups: z.array(zManifestGroup).optional(),\n whitelists: z.array(zManifestWhitelist).optional(),\n policies: z.array(zManifestPolicy).optional(),\n accounts: z.array(zManifestAccount).optional(),\n pledges: z.array(zManifestPledgeAdjustment).optional(),\n })\n .strict()\n .describe(\"Workspace configuration\");\n\nexport type ManifestWorkspace = z.infer<typeof zManifestWorkspace>;\n\n// #endregion\n\n// #region ---------- Tradelink organization ------------------------------------------------------\n\nconst zManifestTradelinkOrgEntity = z\n .object({\n name: z.string(),\n code: z.string(),\n logo: z.string(),\n })\n .strict()\n .describe(\"Tradelink organization entity\");\n\nconst zManifestTradelinkOrg = z\n .object({\n exchanges: z.array(zManifestTradelinkOrgEntity).optional(),\n assetManagers: z.array(zManifestTradelinkOrgEntity).optional(),\n custodians: z.array(zManifestTradelinkOrgEntity).optional(),\n })\n .strict()\n .describe(\"Tradelink organization configuration\");\n\nexport type ManifestTradelinkOrg = z.infer<typeof zManifestTradelinkOrg>;\n\n// #endregion\n\n// #region ---------- Manifest --------------------------------------------------------------------\n\nexport const zManifest = z\n .object({\n manifestVersion: z.literal(2),\n tradelink: zManifestTradelinkOrg.optional(),\n workspace: zManifestWorkspace.optional(),\n })\n .strict();\n\nexport type Manifest = z.infer<typeof zManifest>;\n\n// #endregion\n"],"mappings":";;;;;;AAAA,OAAOA,gBAAe;;;ACAtB,OAAOC,gBAAe;;;ACCtB,OAAO,eAAe;AAcf,SAAS,qBAAqB,QAA4B;AAC/D,SAAO;AAAA,IACL,SAAS,OAAqB;AAC5B,aAAO,KAAK,MAAM,KAAK,KAAK;AAAA,IAC9B;AAAA,IACA,QAAQ,KAAmB;AACzB,aAAO,KAAK,MAAM,GAAG,EAAE;AAAA,IACzB;AAAA,IACA,WAAW,KAAmB;AAC5B,aAAO,KAAK,SAAS,GAAG,EAAE;AAAA,IAC5B;AAAA,EACF;AACF;AAOA,eAAsB,eACpB,SACA,WACA,QAC+B;AAC/B,QAAM,EAAE,WAAW,IAAI,qBAAqB,MAAM;AAClD,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,eAAW,wBAAwB,IAAI,CAAC,IAAI,UAAU,MAAM,MAAM;AAClE,UAAM,WAAW,UAAU,CAAC;AAC5B,cAAU,MAAM,SAAS,QAAQ,OAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAEA,eAAsB,wBACpB,OACA,WACA,QAC+B;AAC/B,QAAM,EAAE,WAAW,IAAI,qBAAqB,MAAM;AAClD,QAAM,UAAU,UAAU,CAAC;AAC3B,YAAU,SAAS,0CAA0C;AAC7D,aAAW,4BAA4B,MAAM,IAAI,KAAK;AACtD,QAAM,UAAU,MAAM,QAAQ,OAAO,SAAS,OAAO,OAAO,EAAE,SAAS,MAAM,CAAC;AAC9E,SAAO,eAAe,SAAS,WAAW,MAAM;AAClD;;;AD7CA,IAAM,mBAAmB,CAAC,WAA8D;AACtF,SAAO,OAAO,OAAiB,CAAC,KAAK,QAAQ;AAC3C,QAAI,KAAK,GAAG,IAAI,QAAQ,MAAM,GAAG,IAAI,MAAM,CAAC;AAC5C,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACP;AAEA,eAAsB,qBAAqB,SAAkB,QAA+B;AAC1F,QAAM,EAAE,kBAAkB,OAAO,IAAI;AAErC,QAAM,iBAAiB,0BAA0B,MAAM;AAEvD,SAAO,KAAK,0BAA0B;AACtC,QAAM,QAAQ,MAAM,OAAO,gBAAgB,CAAC,EAAE,MAAM;AAEpD,SAAO,KAAK,sDAAsD;AAClE,QAAM,CAAC,kBAAkB,WAAW,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC/D,SAAS,MAAM,OAAO,SAAS,KAAK,OAAO,EAAE,MAAM,iBAAiB,QAAQ,CAAC;AAAA,IAC7E,MAAM,OAAO,UAAU,oBAAoB,MAAM;AAAA,IACjD,MAAM,OAAO,UAAU,WAAW,MAAM;AAAA,EAC1C,CAAC;AAED,QAAM,UAAU,iBAAiB,KAAK,CAACC,aAAYA,SAAQ,SAAS,iBAAiB,OAAO;AAC5F,EAAAC,WAAU,SAAS,WAAW,iBAAiB,OAAO,YAAY;AAElE,EAAAA,WAAU,WAAW,wCAAwC;AAC7D,EAAAA,WAAU,SAAS,sCAAsC;AAEzD,QAAM,WAAW,QAAQ,UAAU,KAAK,CAACC,cAAa;AACpD,UAAM,oBAAoB,UAAU,UAAU;AAAA,MAC5C,CAACC,uBAAsBA,mBAAkB,gBAAgBD,UAAS;AAAA,IACpE;AACA,IAAAD,WAAU,mBAAmB,YAAYC,UAAS,WAAW,yBAAyB;AACtF,WAAO,kBAAkB,SAAS,iBAAiB;AAAA,EACrD,CAAC;AACD,EAAAD,WAAU,UAAU,YAAY,iBAAiB,QAAQ,uBAAuB;AAEhF,QAAM,aAAa,QAAQ;AAC3B,EAAAA,WAAU,WAAW,SAAS,aAAa,qCAAqC;AAChF,QAAM,eAAe,QAAQ,cAAc,KAAK,CAAC,OAAO,GAAG,OAAO,WAAW,cAAc;AAC3F,EAAAA,WAAU,cAAc,iBAAiB,WAAW,cAAc,uBAAuB;AAEzF,QAAM,iCAAiC,CAAC,CAAC,WAAW,gBAAgB;AAAA,IAClE,CAAC,MAAM,EAAE,eAAe,SAAS;AAAA,EACnC;AACA,EAAAA;AAAA,IACE;AAAA,IACA,YAAY,SAAS,EAAE,kCAAkC,QAAQ,EAAE;AAAA,EACrE;AAEA,QAAM,cAAc;AAAA,IAClB,GAAG,iBAAiB,aAAa,MAAM;AAAA,IACvC,GAAG,iBAAiB,SAAS,MAAM;AAAA,EACrC;AAEA,QAAM,YAAY,MAAM,QAAQ;AAAA,IAC9B,YAAY;AAAA,MAAI,CAAC,OACf,MAAM,OAAO,MAAM,SAChB,MAAM,EAAE,GAAG,CAAC,EACZ,KAAK,CAAC,SAAS,eAAe,KAAK,YAAa,CAAC,EACjD,KAAK,CAAC,UAAU,OAAO,gBAAgB,KAAK,EAAE,MAAM,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM;AAAA,IACJ;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,WAAW,QAAQ;AAAA,QACnB,YAAY,SAAS;AAAA,QACrB,QAAQ,iBAAiB;AAAA,MAC3B;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,4CAA4C,iBAAiB,OAAO,gBAAgB,iBAAiB,QAAQ;AAAA,EAC/G;AACF;;;AEnFA,eAAsB,0BAA0B,SAAkB,QAA+B;AAC/F,QAAM,EAAE,WAAW,QAAQ,eAAe,iBAAiB,IAAI;AAE/D,QAAM,EAAE,QAAQ,IAAI,qBAAqB,MAAM;AAE/C,QAAM,aAAa,OAAO,aAAa,EAAE,cAAc,CAAC;AACxD,MAAI,UAAU,WAAW;AACvB,YAAQ,8CAA8C;AACtD,UAAM,uBAAuB,MAAM,WAAW,UAAU,KAAK,iBAAiB,MAAM;AACpF,eAAW,eAAe,UAAU,WAAW;AAC7C,YAAM,sBAAsB,qBAAqB,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,IAAI;AACxF,UAAI,qBAAqB;AACvB,eAAO;AAAA,UACL,mCAAmC,oBAAoB,IAAI,KAAK,oBAAoB,IAAI;AAAA,QAC1F;AAAA,MACF,OAAO;AACL,cAAM,WAAW,UAAU,KAAK,kBAAkB,OAAO;AAAA,UACvD,MAAM,YAAY;AAAA,UAClB,MAAM,YAAY;AAAA,UAClB,SAAS,YAAY;AAAA,QACvB,CAAC;AACD,eAAO,KAAK,iCAAiC,YAAY,IAAI,KAAK,YAAY,IAAI,GAAG;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,eAAe;AAC3B,YAAQ,mDAAmD;AAC3D,UAAM,wBAAwB,MAAM,WAAW,UAAU,KAAK,qBAAqB,MAAM;AACzF,eAAW,mBAAmB,UAAU,eAAe;AACrD,YAAM,0BAA0B,sBAAsB;AAAA,QACpD,CAAC,MAAM,EAAE,SAAS,gBAAgB;AAAA,MACpC;AACA,UAAI,yBAAyB;AAC3B,eAAO;AAAA,UACL,wCAAwC,wBAAwB,IAAI,KAAK,wBAAwB,IAAI;AAAA,QACvG;AAAA,MACF,OAAO;AACL,cAAM,WAAW,UAAU,KAAK,sBAAsB,OAAO;AAAA,UAC3D,MAAM,gBAAgB;AAAA,UACtB,MAAM,gBAAgB;AAAA,UACtB,SAAS,gBAAgB;AAAA,QAC3B,CAAC;AACD,eAAO;AAAA,UACL,sCAAsC,gBAAgB,IAAI,KAAK,gBAAgB,IAAI;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,YAAY;AACxB,YAAQ,+CAA+C;AACvD,UAAM,qBAAqB,MAAM,WAAW,UAAU,KAAK,kBAAkB,MAAM;AACnF,eAAW,gBAAgB,UAAU,YAAY;AAC/C,YAAM,uBAAuB,mBAAmB,KAAK,CAAC,MAAM,EAAE,SAAS,aAAa,IAAI;AACxF,UAAI,sBAAsB;AACxB,eAAO;AAAA,UACL,oCAAoC,qBAAqB,IAAI,KAAK,qBAAqB,IAAI;AAAA,QAC7F;AAAA,MACF,OAAO;AACL,cAAM,WAAW,UAAU,KAAK,mBAAmB,OAAO;AAAA,UACxD,MAAM,aAAa;AAAA,UACnB,MAAM,aAAa;AAAA,UACnB,SAAS,aAAa;AAAA,QACxB,CAAC;AACD,eAAO,KAAK,kCAAkC,aAAa,IAAI,KAAK,aAAa,IAAI,GAAG;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AACA,MAAI,kBAAkB;AACpB,YAAQ,yCAAyC;AACjD,UAAM,EAAE,eAAe,UAAU,IAAI;AACrC,UAAM,qBAAqB,MAAM,WAAW,UAAU,KAAK,sBAAsB,MAAM;AACvF,UAAM,oBAAoB,mBAAmB,KAAK,CAAC,MAAM,EAAE,kBAAkB,aAAa;AAC1F,QAAI,mBAAmB;AACrB,aAAO,KAAK,mCAAmC,aAAa,2BAA2B;AAAA,IACzF,OAAO;AACL,YAAM,WAAW,UAAU,KAAK,uBAAuB,OAAO;AAAA,QAC5D;AAAA,QACA,WAAW,EAAE,MAAM,UAAU,UAAU;AAAA,QACvC,WAAW,UAAU,UAAU,IAAI,CAACG,QAAO,EAAE,MAAMA,GAAE,EAAE;AAAA,QACvD,eAAe,UAAU,cAAc,IAAI,CAACA,QAAO,EAAE,MAAMA,GAAE,EAAE;AAAA,MACjE,CAAC;AACD,aAAO,KAAK,iCAAiC,iBAAiB,aAAa,YAAY;AAAA,IACzF;AAAA,EACF;AACF;;;AC1FA,OAAOC,gBAAe;AACtB,OAAO,OAAO;AAiCd,eAAsB,cAAc,SAAkB,QAA+B;AACnF,QAAM,EAAE,WAAW,QAAQ,cAAc,IAAI;AAE7C,QAAM,kBAAkB,OAAO,cAAc,aAAa;AAC1D,QAAM,EAAE,UAAU,SAAS,WAAW,IAAI,qBAAqB,MAAM;AAGrE,QAAM,kBAAkB,0BAA0B,eAAe;AAIjE,SAAO,KAAK,mCAAmC;AAC/C,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzC,gBAAgB,gBAAgB,CAAC,EAAE,MAAM;AAAA,IACzC,gBAAgB,gBAAgB,CAAC,EAAE,MAAM;AAAA,EAC3C,CAAC;AAGD,SAAO,KAAK,2BAA2B;AACvC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpB,SAAS,OAAO,OAAO,MAAM,KAAK,OAAO,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC7D,SAAS,OAAO,OAAO,OAAO,KAAK,OAAO,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC9D,SAAS,OAAO,OAAO,SAAS,KAAK,OAAO,EAAE,WAAW,MAAM,CAAC;AAAA,IAChE,SAAS,OAAO,OAAO,SAAS,KAAK,OAAO,EAAE,QAAQ,UAAU,cAAc,KAAK,CAAC;AAAA,IACpF,OAAO,OAAO,UAAU,oBAAoB,MAAM;AAAA,EACpD,CAAC;AAED,QAAM,8BAA8B,EAAE,MAAM,2BAA2B,WAAW,MAAM;AACxF,QAAM,kCAAkC,EAAE,MAAM,2BAA2B,eAAe,MAAM;AAEhG,MAAI,2BAA2B,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM;AAI9E,QAAM,mBAAmB,cAAc,OAAO,CAAC,SAAS,KAAK,eAAe,KAAK;AACjF,QAAM,mBAAmB,cAAc,OAAO,CAAC,SAAS,KAAK,eAAe,KAAK;AAEjF,QAAM,uBAAuB,MAAM,sBAAsB,gBAAgB;AAKzE,MAAI,UAAU,OAAO;AACnB,aAAS,OAAO;AAChB,QAAI,UAAU,MAAM,QAAQ;AAC1B,iBAAW,eAAe,UAAU,MAAM,QAAQ;AAChD,cAAM,WAAW,SAAS,WAAW;AAAA,MACvC;AAAA,IACF;AACA,QAAI,UAAU,MAAM,WAAW;AAC7B,iBAAW,eAAe,UAAU,MAAM,WAAW;AACnD,cAAM,WAAW,YAAY,WAAW;AAAA,MAC1C;AAAA,IACF;AACA,QAAI,UAAU,MAAM,KAAK;AACvB,iBAAW,WAAW,UAAU,MAAM,KAAK;AACzC,cAAM,cAAc,OAAO;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAKA,MAAI,UAAU,QAAQ;AACpB,aAAS,QAAQ;AACjB,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,YAAY,KAAK;AAAA,IACzB;AAAA,EACF;AAKA,MAAI,UAAU,YAAY;AACxB,aAAS,YAAY;AACrB,UAAM,iBAAiB,UAAU,UAAU;AAAA,EAC7C;AAIA,MAAI,UAAU,UAAU;AACtB,aAAS,UAAU;AACnB,eAAW,UAAU,UAAU,UAAU;AACvC,YAAM,aAAa,MAAM;AAAA,IAC3B;AAAA,EACF;AAKA,MAAI,UAAU,WAAW;AACvB,aAAS,WAAW;AACpB,UAAM,gBAAgB,UAAU,SAAS;AAAA,EAC3C;AAKA,MAAI,UAAU,UAAU;AACtB,aAAS,UAAU;AACnB,eAAW,WAAW,UAAU,UAAU;AACxC,YAAM,cAAc,OAAO;AAAA,IAC7B;AAAA,EACF;AAEA,iBAAe,iBAAiB,YAAgD;AAC9E,UAAM,qBAAqB,MAAM,SAAS,OAAO,OAAO,WAAW,KAAK,OAAO;AAAA,MAC7E,QAAQ;AAAA,IACV,CAAC;AACD,eAAW,aAAa,YAAY;AAClC,YAAM,gBAAgB,SAAS;AAAA,IACjC;AAEA,mBAAe,gBAAgB,WAA6C;AAC1E,YAAM,WAAW,mBAAmB,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,IAAI;AAGzE,UAAI,UAAU;AACZ,eAAO,KAAK,wBAAwB,UAAU,IAAI,kBAAkB;AACpE;AAAA,MACF;AAEA,YAAM,QAA4B;AAAA,QAChC,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAEA,YAAM,wBAAwB,OAAO,CAAC,QAAQ,MAAM,GAAG,MAAM;AAC7D,iBAAW,cAAc,UAAU,IAAI,oBAAoB;AAAA,IAC7D;AAAA,EACF;AAEA,WAAS,oBAAoB,MAA2C;AACtE,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK,MAAM,IAAI,CAAC,SAAS;AACpC,YAAI,WAAW,MAAM;AACnB,iBAAO;AAAA,YACL,QAAQ,KAAK;AAAA,YACb,SAAS,gBAAgB,KAAK,KAAK;AAAA,UACrC;AAAA,QACF;AACA,eAAO;AAAA,UACL,QAAQ,KAAK;AAAA,UACb,SAAS,KAAK,QAAQ,IAAI,qBAAqB;AAAA,QACjD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,iBAAe,cAAc,SAAyC;AACpE,UAAM,WAAW,iBAAiB,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,IAAI;AACrE,QAAI,UAAU;AACZ,aAAO,KAAK,sBAAsB,QAAQ,IAAI,kBAAkB;AAChE;AAAA,IACF;AACA,YAAQ,qBAAqB,QAAQ,IAAI,GAAG;AAC5C,UAAM,QAA4B;AAAA,MAChC,MAAM;AAAA,MACN,MAAM;AAAA;AAAA,QAEJ,MAAM,QAAQ;AAAA,QACd,UAAU,QAAQ;AAAA,QAClB,iBAAiB,QAAQ;AAAA,QACzB,OAAO,QAAQ;AAAA;AAAA,QAGf,YACE,QAAQ,WAAW,SAAS,cACxB;AAAA,UACE,MAAM;AAAA,UACN,gBAAgB,uBAAuB,QAAQ,WAAW,YAAY;AAAA,UACtE,iBAAiB,QAAQ,WAAW,UAAU,IAAI,CAAC,oBAAoB;AAAA,YACrE,YAAY,mBAAmB,eAAe,IAAI;AAAA,YAClD,oBAAoB,eAAe,uBAAuB;AAAA,YAC1D,yCACE,eAAe,4CAA4C;AAAA,UAC/D,EAAE;AAAA,QACJ,IACA;AAAA,UACE,MAAM;AAAA,UACN,QAAQ,EAAE,OAAO,QAAQ,WAAW,MAAM,IAAI,mBAAmB,EAAE;AAAA,QACrE;AAAA,MACR;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,wBAAwB,OAAO,CAAC,QAAQ,MAAM,GAAG,MAAM;AAEzE,QAAI,QAAQ,WAAW,SAAS,aAAa;AAC3C,cAAQ,iCAAiC,QAAQ,IAAI,GAAG;AAExD,YAAM,iBAAiB,uBAAuB,QAAQ,WAAW,YAAY;AAC7E,YAAM,eAAe,0BAA0B,cAAc;AAAA,QAC3D,CAACC,kBAAiBA,cAAa,OAAO;AAAA,MACxC;AACA,MAAAC,WAAU,cAAc,kCAAkC;AAC1D,YAAM,8BAA8B,MAAM,QAAQ;AAAA,QAChD,aAAa,OAAO;AAAA,UAAQ,CAAC,EAAE,QAAQ,QAAQ,MAC7C,QAAQ,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,WAAW;AACvC,kBAAM,cAAc,qBAAqB,KAAK,CAAC,MAAM,EAAE,KAAK,OAAO,MAAM,GAAG;AAC5E,mBAAO,gBAAgB,gBAAgB,WAAY,EAAE,MAAM;AAAA,UAC7D,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAM;AAAA,QACJ,EAAE,MAAM,8BAA8B,UAAU,IAAI,UAAW,MAAM,CAAC,EAAE;AAAA,QACxE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,eAAW,WAAW,QAAQ,IAAI,mBAAmB;AAAA,EACvD;AAEA,iBAAe,WAAW,MAA4B,aAAoC;AACxF,UAAM,aAAa,gBAAgB,gBAAgB,WAAW;AAC9D,UAAM,WAAW,MAAM,WAAW,OAAO,gBAAgB;AAGzD,UAAM,WAAW,cAAc,KAAK,CAAC,SAAS,KAAK,iBAAiB,QAAQ;AAC5E,QAAI,UAAU;AACZ,aAAO,KAAK,oCAAoC,WAAW,iBAAiB;AAC5E;AAAA,IACF;AAEA,UAAM,OAAO,GAAG,SAAS,UAAU,UAAU,UAAU,IAAI,WAAW;AACtE,YAAQ,YAAY,IAAI,EAAE;AAE1B,eAAW,wBAAwB;AACnC,QAAI,eAAe,MAAM,OAAO,OAAO,kBAAkB,OAAO,OAAO;AAAA,MACrE;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAED,eAAW,4BAA4B;AACvC,mBAAe,MAAM,WAAW,SAAS,YAAY;AAErD,eAAW,qBAAqB;AAChC,QAAI,MAAM,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,MACnD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,MAAM,EAAE,gBAAgB,aAAa,GAAG;AAAA,MAC1C;AAAA,IACF,CAAC;AAED,UAAM,MAAM,eAAe,KAAK,CAAC,QAAQ,MAAM,GAAG,MAAM;AACxD,eAAW,GAAG,IAAI,mBAAmB;AAErC,UAAM,cAAc,MAAM,OAAO,OAAO,MAAM,SAAS,MAAM,EAAE,IAAI,IAAI,SAAU,CAAC;AAGlF,kBAAc,KAAK,WAAW;AAC9B,yBAAqB,KAAK,EAAE,MAAM,aAAa,YAAY,CAAC;AAAA,EAC9D;AAEA,iBAAe,cAAc,SAAyC;AACpE,UAAM,WAAW,iBAAiB;AAAA,MAChC,CAAC,SAAS,KAAK,WAAW,QAAQ,UAAU,KAAK,SAAS,QAAQ;AAAA,IACpE;AACA,QAAI,UAAU;AACZ,aAAO;AAAA,QACL,gDAAgD,QAAQ,IAAI,oBAAoB,QAAQ,MAAM;AAAA,MAChG;AACA;AAAA,IACF;AAEA,YAAQ,sBAAsB,QAAQ,IAAI,MAAM;AAEhD,eAAW,qBAAqB;AAChC,QAAI,MAAM,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,MACnD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ;AAAA,UACd,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ;AAAA,QACnB;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,MAAM,eAAe,KAAK,CAAC,QAAQ,MAAM,GAAG,MAAM;AACxD,eAAW,aAAa,QAAQ,IAAI,oBAAoB;AAExD,eAAW,2BAA2B;AACtC,UAAM,cAAc,MAAM,OAAO,OAAO,MAAM,wBAAwB,OAAO;AAAA,MAC3E,IAAI,IAAI;AAAA,IACV,CAAC;AACD;AAAA,MACE,aAAa,QAAQ,IAAI,+CAA+C,YAAY,QAAQ,kBAAkB,YAAY,YAAY;AAAA,IACxI;AACA,UAAM,cAAc,MAAM,OAAO,OAAO,MAAM,SAAS,MAAM,EAAE,IAAI,IAAI,SAAU,CAAC;AAElF,qBAAiB,KAAK,WAAW;AAAA,EACnC;AAEA,iBAAe,YAAY,OAAqC;AAC9D,UAAM,WAAW,eAAe,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,IAAI;AACjE,QAAI,UAAU;AACZ,aAAO,KAAK,oBAAoB,MAAM,IAAI,kBAAkB;AAC5D;AAAA,IACF;AAEA,YAAQ,kBAAkB,MAAM,IAAI,KAAK;AAEzC,UAAM,UAAU,MAAM,QAAQ,IAAI,qBAAqB;AAEvD,eAAW,qBAAqB;AAChC,QAAI,UAAU,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,MACvD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,MAAM,MAAM;AAAA,UACZ,aAAa;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,cAAU,MAAM,eAAe,SAAS,CAAC,QAAQ,MAAM,GAAG,MAAM;AAChE,eAAW,GAAG,MAAM,IAAI,mBAAmB;AAE3C,UAAM,eAAe,MAAM,OAAO,OAAO,OAAO,SAAS,MAAM,EAAE,IAAI,QAAQ,SAAU,CAAC;AACxF,mBAAe,KAAK,YAAY;AAAA,EAClC;AAEA,iBAAe,aAAa,QAAuC;AACjE,UAAM,WAAW,iBAAiB,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI;AACpE,QAAI,UAAU;AACZ,aAAO,KAAK,qBAAqB,OAAO,IAAI,kBAAkB;AAC9D;AAAA,IACF;AAEA,YAAQ,mBAAmB,OAAO,IAAI,KAAK;AAE3C,eAAW,qBAAqB;AAChC,QAAI,UAAU,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,MACvD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,MAAM,OAAO;AAAA,UACb,UAAU,OAAO;AAAA,UACjB,aAAa;AAAA,UACb,UAAU,OAAO,MAAM,IAAI,mBAAmB;AAAA,QAChD;AAAA,MACF;AAAA,IACF,CAAC;AAED,cAAU,MAAM,eAAe,SAAS,CAAC,QAAQ,MAAM,GAAG,MAAM;AAChE,eAAW,GAAG,OAAO,IAAI,mBAAmB;AAE5C,UAAM,gBAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,SAAU,CAAC;AAC3F,qBAAiB,KAAK,aAAa;AAAA,EACrC;AAEA,iBAAe,gBAAgB,WAAoD;AACjF,QAAI,UAAU,WAAW;AACvB,UAAI,6BAA6B,MAAM;AACrC,gBAAQ,8BAA8B;AACtC,cAAM,EAAE,YAAY,UAAU,YAAY,IAAI,UAAU;AACxD,cAAM,OAAO;AAAA,UACX,YAAY,WAAW,IAAI,+BAA+B;AAAA,UAC1D,UAAU,SAAS,IAAI,+BAA+B;AAAA,UACtD,aAAa,YAAY,IAAI,+BAA+B;AAAA,QAC9D;AAEA,mBAAW,qBAAqB;AAChC,cAAM,UAAU,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,UACzD,SAAS;AAAA,YACP,MAAM;AAAA,YACN;AAAA,UACF;AAAA,QACF,CAAC;AAED,cAAM,eAAe,SAAS,CAAC,QAAQ,MAAM,GAAG,MAAM;AACtD,mBAAW,6CAA6C;AAExD,mCAA2B,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM;AAAA,MAC5E,OAAO;AACL,eAAO,KAAK,2CAA2C;AAAA,MACzD;AAEA,YAAM,mBAAmB,MAAM,OAAO,OAAO,UAAU,oBAAoB,MAAM;AACjF,UAAI,qBAAqB,MAAM;AAC7B,YAAI,UAAU,cAAc,QAAW;AACrC,gBAAM,yBAAyB,kBAAkB,UAAU,SAAS;AAAA,QACtE;AAEA,YAAI,UAAU,kBAAkB,QAAW;AACzC,gBAAM,6BAA6B,kBAAkB,UAAU,aAAa;AAAA,QAC9E;AAAA,MACF,OAAO;AACL,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,yBACb,kBACA,WACe;AACf,IAAAA,WAAU,6BAA6B,MAAM,sBAAsB;AACnE,UAAM,qBAAqB,iBAAiB;AAC5C,eAAW,YAAY,WAAW;AAEhC,YAAM,oBAAoB,mBAAmB,KAAK,CAAC,EAAE,KAAK,MAAM,SAAS,SAAS,IAAI;AACtF,MAAAA;AAAA,QACE,sBAAsB;AAAA,QACtB,YAAY,SAAS,IAAI;AAAA,MAC3B;AACA,YAAM,aAAa,kBAAkB;AACrC,cAAQ,qBAAqB,SAAS,IAAI,KAAK;AAC/C,UACE,yBAAyB,UAAU,KAAK,CAAC,EAAE,YAAY,MAAM,gBAAgB,UAAU,MACvF,QACA;AACA,eAAO,KAAK,uBAAuB,SAAS,IAAI,kBAAkB;AAClE;AAAA,MACF;AAEA,iBAAW,qBAAqB;AAChC,YAAM,UAAU,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,QACzD,SAAS;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,aAAa;AAAA,YACb,QAAQ,SAAS,OAAO,IAAI,+BAA+B;AAAA,YAC3D,WAAW,SAAS;AAAA,UACtB;AAAA,QACF;AAAA,MACF,CAAC;AAED,YAAM,0BAA0B,MAAM,QAAQ;AAAA,QAC5C,SAAS,OAAO;AAAA,UAAQ,CAAC,EAAE,QAAQ,QAAQ,MACzC,QACG,MAAM,GAAG,MAAM,EACf,IAAI,CAAC,gBAAgB,gBAAgB,gBAAgB,WAAW,EAAE,MAAM,CAAC;AAAA,QAC9E;AAAA,MACF;AAEA,YAAM,eAAe,SAAS,CAAC,QAAQ,QAAQ,GAAG,uBAAuB,GAAG,MAAM;AAGlF,iCAA2B,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM;AAC1E,MAAAA,WAAU,6BAA6B,MAAM,0BAA0B;AAAA,IACzE;AAAA,EACF;AAEA,iBAAe,6BACb,kBACA,eACe;AACf,IAAAA,WAAU,6BAA6B,MAAM,sBAAsB;AACnE,UAAM,yBAAyB,iBAAiB;AAChD,eAAW,gBAAgB,eAAe;AAExC,YAAM,wBAAwB,uBAAuB;AAAA,QACnD,CAAC,EAAE,KAAK,MAAM,SAAS,aAAa;AAAA,MACtC;AACA,MAAAA;AAAA,QACE,0BAA0B;AAAA,QAC1B,gBAAgB,aAAa,IAAI;AAAA,MACnC;AACA,YAAM,iBAAiB,sBAAsB;AAC7C,cAAQ,yBAAyB,aAAa,IAAI,KAAK;AACvD,UACE,yBAAyB,cAAc;AAAA,QACrC,CAAC,EAAE,YAAY,MAAM,gBAAgB;AAAA,MACvC,MAAM,QACN;AACA,eAAO,KAAK,4BAA4B,aAAa,IAAI,kBAAkB;AAC3E;AAAA,MACF;AAEA,iBAAW,qBAAqB;AAChC,YAAM,UAAU,MAAM,OAAO,OAAO,SAAS,OAAO,OAAO;AAAA,QACzD,SAAS;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,aAAa;AAAA,YACb,QAAQ,aAAa,OAAO,IAAI,+BAA+B;AAAA,YAC/D,WAAW,aAAa;AAAA,UAC1B;AAAA,QACF;AAAA,MACF,CAAC;AAED,YAAM,8BAA8B,MAAM,QAAQ;AAAA,QAChD,aAAa,OAAO;AAAA,UAAQ,CAAC,EAAE,QAAQ,QAAQ,MAC7C,QACG,MAAM,GAAG,MAAM,EACf,IAAI,CAAC,gBAAgB,gBAAgB,gBAAgB,WAAW,EAAE,MAAM,CAAC;AAAA,QAC9E;AAAA,MACF;AAEA,YAAM,eAAe,SAAS,CAAC,QAAQ,QAAQ,GAAG,2BAA2B,GAAG,MAAM;AAGtF,iCAA2B,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM;AAC1E,MAAAA,WAAU,6BAA6B,MAAM,0BAA0B;AAAA,IACzE;AAAA,EACF;AAKA,iBAAe,sBACb,OACwD;AACxD,UAAMC,wBAAuB,MAAM,MAAM;AAAA,MAGvC,CAAC,KAAK,QACJ,IAAI,KAAK,OAAOC,SAAQ;AACtB,QAAAA,KAAI,KAAK,MAAM,gBAAgB,GAAG,CAAC;AACnC,eAAOA;AAAA,MACT,CAAC;AAAA,MACH,QAAQ,QAAQ,CAAC,CAAC;AAAA,IACpB;AACA,WAAOD;AAAA,EACT;AAEA,iBAAe,gBACb,MACsD;AACtD,IAAAD,WAAU,KAAK,cAAc,QAAQ,KAAK,EAAE,mCAAmC;AAC/E,UAAM,cAAc,MAAM,gBAAgB,KAAK,YAAY;AAC3D,WAAO,EAAE,MAAM,YAAY;AAAA,EAC7B;AAEA,WAAS,sBAAsB,aAA6B;AAC1D,UAAM,gBAAgB,qBAAqB,KAAK,CAAC,MAAM,EAAE,gBAAgB,WAAW;AACpF,IAAAA,WAAU,eAAe,6BAA6B,WAAW,EAAE;AACnE,WAAO,cAAc,KAAK;AAAA,EAC5B;AAEA,WAAS,gBAAgB,WAA2B;AAClD,UAAM,QAAQ,eAAe,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS;AAC7D,IAAAA,WAAU,OAAO,SAAS,SAAS,YAAY;AAC/C,WAAO,MAAM;AAAA,EACf;AAEA,WAAS,uBAAuB,kBAAkC;AAChE,UAAM,kBAAkB,gCAAgC,gBAAgB;AACxE,IAAAA;AAAA,MACE;AAAA,MACA,mDAAmD,gBAAgB;AAAA,IACrE;AACA,UAAM,eAAe,0BAA0B,cAAc;AAAA,MAC3D,CAACD,kBAAiBA,cAAa,gBAAgB,gBAAgB;AAAA,IACjE;AACA,IAAAC,WAAU,cAAc,qCAAqC,gBAAgB,EAAE;AAC/E,WAAO,aAAa;AAAA,EACtB;AAEA,WAAS,mBAAmB,cAA8B;AACxD,UAAM,WAAW,0BAA0B,UAAU,KAAK,CAACG,cAAa;AACtE,YAAM,cAAc,4BAA4B,YAAY;AAC5D,MAAAH,WAAU,aAAa,8CAA8CG,UAAS,WAAW,EAAE;AAC3F,aAAO,YAAY,SAAS;AAAA,IAC9B,CAAC;AACD,IAAAH,WAAU,UAAU,iCAAiC,YAAY,EAAE;AACnE,WAAO,SAAS;AAAA,EAClB;AAEA,WAAS,gCAAgC;AAAA,IACvC;AAAA,IACA;AAAA,EACF,GAAgD;AAC9C,WAAO;AAAA,MACL,SAAS,QAAQ,IAAI,qBAAqB;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AACF;;;AC9mBA,OAAO,OAAO;AAiBd,IAAM,gBAAgB,EAAE,OAAO,EAAE,SAAS,mBAAmB;AAC7D,IAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;AAAA,EACzC,MAAM,EAAE,KAAK,CAAC,SAAS,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,QAAQ,UAAU;AAAA,EAChF,QAAQ,EAAE,OAAO,EAAE,SAAS,qBAAqB;AAAA,EACjD,SAAS,EAAE,QAAQ,EAAE,SAAS,4CAA4C;AAC5E,CAAC;AAQD,IAAM,iBAAiB,EACpB,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EACtC,SAAS,EAAE,MAAM,aAAa,EAAE,SAAS,eAAe;AAC1D,CAAC,EACA,OAAO,EACP,SAAS,iBAAiB;AAQ7B,IAAM,4BAA4B,EAC/B,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS,wBAAwB;AAAA,EAClD,UAAU,EAAE,OAAO,EAAE,SAAS,4BAA4B;AAAA,EAC1D,SAAS,EAAE,OAAO,EAAE,SAAS,mBAAmB;AAAA,EAChD,iBAAiB,EACd,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,2DAA2D;AACzE,CAAC,EACA,OAAO;AAEV,IAAM,qBAAqB,EACxB,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS,gBAAgB;AAAA,EAC1C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,SAAS,uBAAuB;AAAA,EAC/E,MAAM,EACH,KAAK,CAAC,eAAe,gBAAgB,CAAC,EACtC,SAAS,EACT,QAAQ,aAAa,EACrB,SAAS,gBAAgB;AAAA,EAC5B,WAAW,EAAE,MAAM,yBAAyB,EAAE,SAAS,qBAAqB;AAC9E,CAAC,EACA,OAAO,EACP,SAAS,WAAW;AAQvB,IAAM,mCAAmC,EACtC,OAAO;AAAA,EACN,QAAQ,EAAE,OAAO;AAAA,EACjB,SAAS,EAAE,MAAM,aAAa;AAChC,CAAC,EACA,OAAO;AAEV,IAAM,mCAAmC,EACtC,OAAO;AAAA,EACN,QAAQ,EAAE,OAAO;AAAA,EACjB,OAAO,EAAE,OAAO;AAClB,CAAC,EACA,OAAO;AAEV,IAAM,0BAA0B,EAAE,MAAM;AAAA,EACtC;AAAA,EACA;AACF,CAAC;AAED,IAAM,0BAA0B,EAC7B,OAAO;AAAA;AAAA;AAAA,EAGN,MAAM,EAAE,KAAK,CAAC,QAAQ,SAAS,mBAAmB,oBAAoB,cAAc,CAAC;AAAA,EACrF,OAAO,EAAE,MAAM,uBAAuB,EAAE,IAAI,CAAC;AAC/C,CAAC,EACA,OAAO;AAIH,IAAM,kBAAkB,EAC5B,OAAO;AAAA,EACN,MAAM,EAAE,OAAO;AAAA,EACf,UAAU,EAAE,OAAO;AAAA,EACnB,OAAO,EAAE,MAAM,uBAAuB;AACxC,CAAC,EACA,OAAO;AAQV,IAAM,oCAAoC,EACvC,OAAO;AAAA,EACN,MAAM,EAAE,QAAQ,SAAS;AAAA,EACzB,OAAO,EAAE,MAAM,uBAAuB;AACxC,CAAC,EACA,OAAO;AAEV,IAAM,mCAAmC,EACtC,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;AAAA,EACzC,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,gCAAgC;AAAA,EACpF,yCAAyC,EACtC,QAAQ,EACR,SAAS,EACT,SAAS,8CAA8C;AAC5D,CAAC,EACA,OAAO;AAEV,IAAM,sCAAsC,EACzC,OAAO;AAAA,EACN,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,cAAc,EAAE,OAAO,EAAE,SAAS,oBAAoB;AAAA,EACtD,WAAW,EAAE,MAAM,gCAAgC;AACrD,CAAC,EACA,OAAO;AAEV,IAAM,6BAA6B,EAAE,mBAAmB,QAAQ;AAAA,EAC9D;AAAA,EACA;AACF,CAAC;AAED,IAAM,mBAAmB,EACtB,OAAO;AAAA,EACN,MAAM,EAAE,OAAO;AAAA,EACf,UAAU,EAAE,OAAO;AAAA,EACnB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS;AAAA,EACzC,iBAAiB,EAAE,OAAO,EAAE,SAAS;AAAA,EACrC,YAAY;AACd,CAAC,EACA,OAAO;AAQV,IAAM,4BAA4B,EAC/B,OAAO;AAAA,EACN,SAAS,EAAE,OAAO;AAAA,EAClB,UAAU,EAAE,OAAO;AAAA,EACnB,QAAQ,EAAE,OAAO;AACnB,CAAC,EACA,OAAO;AAQV,IAAM,0BAA0B,EAC7B,OAAO;AAAA,EACN,SAAS,EAAE,MAAM,aAAa;AAAA,EAC9B,QAAQ,EAAE,OAAO;AACnB,CAAC,EACA,OAAO,EACP,SAAS,iBAAiB;AAI7B,IAAM,2BAA2B,EAAE,MAAM,uBAAuB;AAEhE,IAAM,qCAAqC,EACxC,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAC3B,CAAC,EACA,OAAO,EACP,SAAS,6BAA6B;AAEzC,IAAM,8BAA8B,EACjC,MAAM,kCAAkC,EACxC,SAAS,qBAAqB;AAEjC,IAAM,2BAA2B,EAC9B,OAAO;AAAA,EACN,MAAM,EAAE,OAAO;AAAA,EACf,QAAQ;AAAA,EACR,WAAW;AACb,CAAC,EACA,OAAO;AAIV,IAAM,8BAA8B,EACjC,OAAO;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,aAAa;AACf,CAAC,EACA,OAAO;AAEV,IAAM,qCAAqC,EACxC,OAAO;AAAA,EACN,WAAW,EAAE,OAAO;AAAA,EACpB,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC7B,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC;AACnC,CAAC,EACA,OAAO;AAIV,IAAM,4BAA4B,EAC/B,OAAO;AAAA,EACN,kBAAkB,mCAAmC,SAAS;AAAA,EAC9D,WAAW,4BAA4B,SAAS;AAAA,EAChD,WAAW,EAAE,MAAM,wBAAwB,EAAE,SAAS;AAAA,EACtD,eAAe,EAAE,MAAM,wBAAwB,EAAE,SAAS;AAC5D,CAAC,EACA,OAAO,EACP,SAAS,iCAAiC;AAQ7C,IAAM,qBAAqB,EACxB,OAAO;AAAA,EACN,WAAW,0BAA0B,SAAS;AAAA,EAC9C,OAAO,EACJ,OAAO;AAAA,IACN,QAAQ,EAAE,MAAM,aAAa,EAAE,SAAS;AAAA,IACxC,WAAW,EAAE,MAAM,aAAa,EAAE,SAAS;AAAA,IAC3C,KAAK,EAAE,MAAM,gBAAgB,EAAE,SAAS;AAAA,EAC1C,CAAC,EACA,SAAS;AAAA,EACZ,QAAQ,EAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EACzC,YAAY,EAAE,MAAM,kBAAkB,EAAE,SAAS;AAAA,EACjD,UAAU,EAAE,MAAM,eAAe,EAAE,SAAS;AAAA,EAC5C,UAAU,EAAE,MAAM,gBAAgB,EAAE,SAAS;AAAA,EAC7C,SAAS,EAAE,MAAM,yBAAyB,EAAE,SAAS;AACvD,CAAC,EACA,OAAO,EACP,SAAS,yBAAyB;AAQrC,IAAM,8BAA8B,EACjC,OAAO;AAAA,EACN,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE,OAAO;AACjB,CAAC,EACA,OAAO,EACP,SAAS,+BAA+B;AAE3C,IAAM,wBAAwB,EAC3B,OAAO;AAAA,EACN,WAAW,EAAE,MAAM,2BAA2B,EAAE,SAAS;AAAA,EACzD,eAAe,EAAE,MAAM,2BAA2B,EAAE,SAAS;AAAA,EAC7D,YAAY,EAAE,MAAM,2BAA2B,EAAE,SAAS;AAC5D,CAAC,EACA,OAAO,EACP,SAAS,sCAAsC;AAQ3C,IAAM,YAAY,EACtB,OAAO;AAAA,EACN,iBAAiB,EAAE,QAAQ,CAAC;AAAA,EAC5B,WAAW,sBAAsB,SAAS;AAAA,EAC1C,WAAW,mBAAmB,SAAS;AACzC,CAAC,EACA,OAAO;;;ALnSV,eAAsB,aAAa,SAAsB,QAA+B;AACtF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,EAAE,WAAW,UAAU;AAAA,EACnC,IAAI;AAEJ,MAAI,WAAW;AACb,IAAAI,WAAU,eAAe,4DAA4D;AACrF,UAAM;AAAA,MACJ;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAI,WAAW,WAAW,oBAAoB,gBAC1C,EAAE,kBAAkB,EAAE,WAAW,UAAU,UAAU,kBAAkB,cAAc,EAAE,IACvF,CAAC;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,WAAW;AACb,IAAAA,WAAU,eAAe,0DAA0D;AACnF,UAAM,cAAc,EAAE,QAAQ,WAAW,cAAc,GAAG,MAAM;AAEhE,QAAI,UAAU,SAAS;AACrB,YAAM,sBAAsB,OAAO,cAAc,aAAa;AAC9D,iBAAW,oBAAoB,UAAU,SAAS;AAChD,cAAM,qBAAqB,EAAE,QAAQ,qBAAqB,iBAAiB,GAAG,MAAM;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,KAAK,oBAAoB;AAClC;","names":["invariant","invariant","account","invariant","exchange","blueprintExchange","_","invariant","assetManager","invariant","usersWithDeviceIndex","acc","exchange","invariant"]}
package/lib/engine.cjs CHANGED
@@ -344,7 +344,7 @@ var _superjson = require('superjson'); var _superjson2 = _interopRequireDefault(
344
344
  var createClient = (options) => {
345
345
  const trpc = _client.createTRPCClient.call(void 0, {
346
346
  links: [
347
- _client.httpBatchLink.call(void 0, {
347
+ _client.httpLink.call(void 0, {
348
348
  url: `${options.baseUrl}/trpc`,
349
349
  transformer: _superjson2.default,
350
350
  headers() {
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/_work/revault/revault/packages/sdk/lib/engine.cjs","../src/engine/index.ts","../src/device/real-device.ts","../src/trpc.ts"],"names":["withApiUser","withWorkspace","withOnboarding","client","engine"],"mappings":"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","file":"/home/runner/_work/revault/revault/packages/sdk/lib/engine.cjs","sourcesContent":[null,"import type {\n ApiChallenge,\n ClaimedRole,\n OnboardingSeedChallenge,\n PsdChallenge,\n UserRegistrationChallenge,\n UserRegistrationChallengeResponse,\n UserRegistrationDeviceData,\n UserRegistrationResponse,\n VaultRequestResponse,\n WrappingKeyResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport { type Device, createApiDevice } from \"@/device\";\nimport { createRealDevice } from \"@/device/real-device\";\nimport { type TRPCClientOptions, createClient } from \"@/trpc\";\nimport type { Logger } from \"@/types\";\n\nimport type {\n ApproveRequestParams,\n DecorateWithApiUserAndWorkspaceUnauthenticated,\n DecorateWithDevice,\n DecorateWithDeviceAndOnboarding,\n DecorateWithDeviceAndWorkspaceUnauthenticated,\n DecorateWithWorkspaceApiAuthenticated,\n DecorateWithWorkspacePsdAuthenticated,\n DecorateWithWorkspaceUnauthenticated,\n Engine,\n EngineBase,\n EngineOptions,\n RegisterOnboardingDeviceParams,\n WithApiAuth,\n WithApiUser,\n WithDevice,\n WithOnboarding,\n WithPsdAuth,\n WithWorkspace,\n} from \"./types\";\n\nexport { fetchAll } from \"../utils\";\n\nexport type * from \"./types\";\n\nasync function genericRegister<T>({\n device,\n name,\n role,\n getChallenge,\n submitChallenge,\n}: {\n device: Device;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n getChallenge: (p: {\n pubKey: string;\n deviceData: UserRegistrationDeviceData;\n }) => Promise<UserRegistrationChallenge>;\n submitChallenge: (p: {\n pubKey: string;\n challengeResponse: UserRegistrationChallengeResponse;\n }) => Promise<T>;\n}): Promise<T> {\n const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([\n device.getAttestation(),\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n const ephemeralPubKey = await device.initPairingHandshake();\n const deviceData: UserRegistrationDeviceData = {\n name,\n pubKey: u2fPubKey.pubKey,\n psdModel: \"STAX\",\n confidentialityKey: confidentialityKey.pubKey,\n psdEphemeralKey: ephemeralPubKey.pubKey,\n psdEphemeralKeyAttestation: {\n ...attestation.attestation,\n signature: ephemeralPubKey.signature,\n },\n };\n const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });\n const pairingPayload = await device.finalizePairingHandshake({\n handshake: challenge.handshake,\n partitionId: challenge.ciphertext,\n handshakeAttestation: challenge.handshakeAttestation,\n });\n const register = await device.register({\n challenge: challenge.challenge,\n u2fRegisterData: challenge.u2fRegisterData,\n name,\n role,\n });\n const validationPubKey = await device.getValidationPubKey();\n const registerData = await device.registerData({ challenge: challenge.challenge });\n const attestationOffset = 67 + register.u2fRegister.readInt8(66);\n const u2fRegister = Buffer.concat([\n register.u2fRegister.slice(0, attestationOffset),\n Buffer.from([attestation.buffer.length]),\n attestation.buffer,\n register.u2fRegister.slice(attestationOffset),\n ]).toString(\"hex\");\n const challengeResponse: UserRegistrationChallengeResponse = {\n registerData,\n certificate: {\n ...attestation.attestation,\n signature: validationPubKey.signature,\n },\n u2fRegister,\n u2fKeyHandle: register.keyHandle.toString(\"hex\"),\n validationKey: validationPubKey.pubKey,\n pairingPayload,\n };\n return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });\n}\n\nexport function createEngine(options: EngineOptions, logger: Logger): Engine {\n const clientOptions: TRPCClientOptions = {\n baseUrl: options.baseUrl,\n };\n const client = createClient(clientOptions);\n const apiDevice = createApiDevice(options, logger);\n\n const base: EngineBase = {\n client,\n createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),\n };\n\n const withDeviceIndex: Engine[\"withDeviceIndex\"] = function <T>(\n this: Engine<T>,\n deviceIndex: number,\n ) {\n const device = apiDevice.with(deviceIndex);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withTransportId: Engine[\"withTransportId\"] = function <T>(\n this: Engine<T>,\n transportId: string,\n ) {\n const device = createRealDevice({ transportId }, logger);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withApiUser: Engine[\"withApiUser\"] = function <T>(this: Engine<T>) {\n const withApiUser: WithApiUser = { __isApiUser: true };\n return decorateEngine({ ...this, ...withApiUser } as Engine<T & WithApiUser>);\n };\n\n const withWorkspace: Engine[\"withWorkspace\"] = function <T>(\n this: Engine<T>,\n workspaceName: string,\n ) {\n const withWorkspace: WithWorkspace = { __workspaceName: workspaceName };\n return decorateEngine({ ...this, ...withWorkspace } as Engine<T & WithWorkspace>);\n };\n\n const withOnboarding: Engine[\"withOnboarding\"] = function <T>(\n this: Engine<T>,\n onboardingId: string,\n ) {\n const withOnboarding: WithOnboarding = { __onboardingId: onboardingId };\n return decorateEngine({ ...this, ...withOnboarding } as Engine<T & WithOnboarding>);\n };\n\n function decorateEngine<T>(\n engine: Engine<\n T &\n Partial<\n WithDevice & WithOnboarding & WithWorkspace & WithPsdAuth & WithApiUser & WithApiAuth\n >\n >,\n ): Engine<T> {\n function decorate<TEnhanced, TDecoration>(\n decorator: (engine: EngineBase & TEnhanced) => TDecoration,\n ): void {\n Object.assign(engine, decorator(engine as EngineBase & TEnhanced));\n }\n\n // DecorateWithDevice\n // -------------------------------------------------------------------------\n if (engine.device) {\n decorate<WithDevice, DecorateWithDevice<T>>(\n (engine) =>\n ({\n getWorkspaces: async (): Promise<string[]> => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });\n return workspaceNames;\n },\n }) satisfies DecorateWithDevice<T>,\n );\n }\n\n // DecorateWithWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {\n decorate<WithWorkspace, DecorateWithWorkspaceUnauthenticated<T>>((engine) => {\n const { __workspaceName } = engine;\n return {\n withPsdToken: function <T>(this: Engine<T>, token: string): Engine<T & WithPsdAuth> {\n const withPsdAuth: WithPsdAuth = { __psdToken: token };\n const psdAuth = `${__workspaceName}:${token}`;\n const client = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client, ...withPsdAuth } as Engine<T & WithPsdAuth>);\n },\n } satisfies DecorateWithWorkspaceUnauthenticated<T>;\n });\n }\n\n // DecorateWithDeviceAndOnboarding\n // -------------------------------------------------------------------------\n if (engine.device && engine.__onboardingId) {\n decorate<WithDevice & WithOnboarding, DecorateWithDeviceAndOnboarding>((engine) => {\n const { device, client, __onboardingId } = engine;\n async function enforcePairing(): Promise<void> {\n if (await device.hasPairing()) return;\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityKey(),\n ]);\n const pairing = await client.onboarding.pairDevicePartition.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data: {\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n },\n });\n await device.setPairing({ pairing });\n }\n return {\n claimDevice: async (params: { role: ClaimedRole; deviceName: string }): Promise<void> => {\n const { role, deviceName } = params;\n const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await client.onboarding.claimDevice.mutate({\n onboardingId: __onboardingId,\n claim: { role, pubKey, deviceName, confidentialityKey },\n });\n },\n\n collectWrappingKeyFragment: async (wrappingKey: WrappingKeyResponse): Promise<void> => {\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await device.openSession({\n secureChannel: {\n pubKey: wrappingKey.ephemeralPubKey,\n certificate: wrappingKey.ephemeralCertificate,\n },\n });\n const { attestation } = await device.getAttestation();\n const blob = await device.generateWrappingKeyFragment();\n await client.onboarding.submitWrappingKeyFragment.mutate({\n pubKey,\n onboardingId: __onboardingId,\n fragment: {\n blob,\n ephemeralPubKey: confidentialityKey.pubKey,\n ephemeralCertificate: {\n ...attestation,\n signature: confidentialityKey.signature,\n },\n },\n });\n },\n\n registerDevice: async (params: RegisterOnboardingDeviceParams): Promise<void> => {\n const { role, name } = params;\n const getChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.generateMasterAdminRegistrationChallenge\n : client.onboarding.generateSharedOwnerRegistrationChallenge;\n const submitChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.submitMasterAdminRegistration\n : client.onboarding.submitSharedOwnerRegistration;\n await genericRegister({\n device: device,\n name,\n role,\n getChallenge: ({ pubKey, deviceData }) =>\n getChallengeMutation.mutate({\n onboardingId: __onboardingId,\n pubKey,\n deviceData,\n }),\n submitChallenge: ({ pubKey, challengeResponse }) =>\n submitChallengeMutation.mutate({\n onboardingId: engine.__onboardingId,\n pubKey,\n // FIXME this should be renamed to `challengeResponse` on backend side\n response: challengeResponse,\n }),\n });\n },\n\n reviewSharedOwner: async (challenge: PsdChallenge): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitReviewByMasterAdminSignature.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n collectSeedFragment: async (challenge: OnboardingSeedChallenge): Promise<void> => {\n await enforcePairing();\n const [{ pubKey }, { attestation }] = await Promise.all([\n device.getU2FPubKey(),\n device.getAttestation(),\n ]);\n await device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n const challengeResponse = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n const kkPattern = await device.startKKPatternAsResponder({\n partitionId: challenge.partitionId,\n handshake: challenge.kkHandshake,\n handshakeAttestation: challenge.kkHandshakeAttestation,\n });\n const approverBlob = await device.generateSeedFragment();\n await client.onboarding.submitSeedFragment.mutate({\n onboardingId: __onboardingId,\n pubKey,\n seedFragment: {\n challengeResponse,\n approverBlob,\n handshake: kkPattern.handshake,\n handshakeAttestation: {\n ...attestation,\n signature: kkPattern.signature,\n },\n },\n });\n },\n } satisfies DecorateWithDeviceAndOnboarding;\n });\n }\n\n // DecorateWithDeviceAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && !engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithDeviceAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { device, client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n opts?: { validityDurationSecs?: number; onScreenDisplayed?: () => void },\n ): Promise<Engine<T & WithPsdAuth>> {\n const { pubKey } = await device.getU2FPubKey();\n const challenge = await client.auth.psd.generateChallenge.mutate({\n pubKey,\n workspaceName: __workspaceName,\n });\n opts?.onScreenDisplayed?.();\n const authentication = await device.authenticate({\n challenge,\n workspaceName: __workspaceName,\n });\n const authPayload = {\n workspaceName: __workspaceName,\n pubKey,\n authentication,\n validityDurationSecs: opts?.validityDurationSecs,\n };\n const { token } = await client.auth.psd.authenticate.mutate({ ...authPayload });\n const withPsdAuth: WithPsdAuth = {\n __psdToken: token,\n };\n const psdAuth = `${engine.__workspaceName}:${token}`;\n const __authClient = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client: __authClient, ...withPsdAuth } as Engine<\n T & WithPsdAuth\n >);\n },\n\n register: (\n registration: UserRegistrationResponse,\n ): Promise<UserRegistrationResponse> => {\n return genericRegister({\n device,\n name: registration.name,\n role: registration.role,\n getChallenge: async ({ deviceData }) => {\n const challenge = await client.userRegistrations.generateChallenge.mutate({\n id: registration.id,\n workspaceName: __workspaceName,\n deviceData,\n });\n return challenge;\n },\n submitChallenge: ({ challengeResponse }) =>\n client.userRegistrations.submitChallenge.mutate({\n workspaceName: __workspaceName,\n id: registration.id,\n challengeResponse,\n }),\n });\n },\n } satisfies DecorateWithDeviceAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithApiUserAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {\n decorate<WithWorkspace & WithApiUser, DecorateWithApiUserAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n credentials: {\n apiKeyId: string;\n apiKeySecret: string;\n },\n ): Promise<Engine<T & WithApiAuth>> {\n const res = await client.auth.authenticate.mutate({\n apiKeyId: credentials.apiKeyId,\n apiKeySecret: credentials.apiKeySecret,\n workspace: __workspaceName,\n });\n const withApiAuth: WithApiAuth = {\n __apiAuth: res,\n };\n const __authClient = engine.createClient({ apiAccessToken: res.accessToken });\n return decorateEngine({ ...this, client: __authClient, ...withApiAuth } as Engine<\n T & WithApiAuth\n >);\n },\n } satisfies DecorateWithApiUserAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithWorkspacePsdAuthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithWorkspacePsdAuthenticated>((engine) => {\n const { client, device } = engine;\n\n async function enforcePairing(): Promise<void> {\n if (await device.hasPairing()) return;\n const confidentialityKey = await device.getConfidentialityKey();\n const pairing = await client.debug.pairDevicePartition.mutate({\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n });\n await device.setPairing({ pairing });\n }\n\n return {\n approve: async (\n request: VaultRequestResponse,\n params?: ApproveRequestParams,\n ): Promise<VaultRequestResponse> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"PSD\", \"Challenge type must be PSD\");\n await enforcePairing();\n await device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"PSD\", signature },\n });\n },\n\n reject: (request: VaultRequestResponse): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({ id: request.id, data: null });\n },\n } satisfies DecorateWithWorkspacePsdAuthenticated;\n });\n }\n\n // DecorateWithWorkspaceApiAuthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__apiAuth) {\n decorate<WithWorkspace & WithApiAuth, DecorateWithWorkspaceApiAuthenticated>((engine) => {\n const { client } = engine;\n return {\n getChallenge: async (request: VaultRequestResponse): Promise<ApiChallenge[\"payload\"]> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"API\", \"Challenge type must be API\");\n return challenge.payload;\n },\n\n approve: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n\n reject: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n } satisfies DecorateWithWorkspaceApiAuthenticated;\n });\n }\n\n return engine;\n }\n\n return {\n ...base,\n withDeviceIndex,\n withTransportId,\n withApiUser,\n withWorkspace,\n withOnboarding,\n };\n}\n","import { DisconnectedDevice, LockedDeviceError } from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport type { HsmCertificate } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { from, lastValueFrom } from \"rxjs\";\n\nimport type { Logger } from \"@/types\";\n\nimport {\n APPID_VAULT_ADMINISTRATOR,\n PAGINATED_STATUS,\n PATHS,\n SCRIPT_IDS,\n STATUS_LENGTH,\n STREAMING_NEXT_ACTION,\n STREAMING_RESPONSE,\n STR_ROLES,\n} from \"./constants\";\nimport { withDevicePolling } from \"./device-access\";\nimport type { Device } from \"./types\";\nimport { isTransportStatusError } from \"./utils\";\n\nconst MAX_CHUNK_LENGTH = 250;\n\ntype Options = {\n transportId: string;\n};\n\nconst FIXME_NOT_IMPLEMENTED =\n (fnName: string): (() => Promise<never>) =>\n async () => {\n throw new Error(`Not implemented: ${fnName}`);\n };\n\nconst getPathFromPathString = (pathString: string): number[] => {\n const parts = pathString.split(\"'/\").map((part) => parseInt(part, 10));\n return parts.map((part) => (part | 0x80000000) >>> 0);\n};\n\nconst splitChunks = (chunk: number, buffer: Buffer): Buffer[] => {\n const chunks = [];\n for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {\n chunks.push(buffer.slice(i, i + size));\n }\n return chunks;\n};\n\nconst removeStatus = (result: Buffer): Buffer => result.slice(0, result.length - STATUS_LENGTH);\n\nconst sendByChunk = async (\n transport: Transport,\n command: number[], // eg [0xe0, 0x45, 0x00, 0x00]\n data: Buffer,\n chunkSize: number = MAX_CHUNK_LENGTH,\n): Promise<Buffer> => {\n const chunks = splitChunks(chunkSize, data);\n let response = Buffer.from([]);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const apdu = [...command];\n // command is 0xe0,0x45,0x00,0x00 for first chunk, then it's 0xe0,0x45,0x80,0x00\n /* v8 ignore start */\n apdu[2] = i && 0x80;\n /* v8 ignore stop */\n response = await transport.send(apdu[0]!, apdu[1]!, apdu[2], apdu[3]!, chunk, [\n 0x9000,\n ...PAGINATED_STATUS,\n ]);\n }\n return response;\n};\n\nconst buildAttestation = (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n}): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const cliMsgBuffer = Buffer.from(params.handshake, \"hex\");\n const cliMsgLengthBuffer = Buffer.alloc(1);\n cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);\n\n const pidBuffer = Buffer.from(params.partitionId, \"hex\");\n const pidLengthBuffer = Buffer.alloc(1);\n pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n cliMsgLengthBuffer,\n cliMsgBuffer,\n certChainDataLengthBuff,\n certChainData,\n pidLengthBuffer,\n pidBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n const toSend = Buffer.concat([totalLengthBuffer, data]);\n\n return toSend;\n};\n\ntype RetryOnError = (err: Error) => boolean;\n/* v8 ignore start */\nconst genericRetryOnError: RetryOnError = (err) => {\n // device is locked\n if (err instanceof LockedDeviceError) return true;\n // user is on dashboard when receiving a Vault app apdu\n if (isTransportStatusError(err) && err.statusCode === 0x6d09) return true;\n // VG-24797 error that can happen in BLE in some situations (still unclear)\n if (err instanceof DisconnectedDevice) return true;\n\n // for everything else, we don't want to retry\n return false;\n};\n/* v8 ignore stop */\n\nexport function createRealDevice(options: Options, logger: Logger): Device {\n const { transportId } = options;\n\n async function run<T>(\n job: (transport: Transport) => Promise<T>,\n retryOnError: RetryOnError = genericRetryOnError,\n ): Promise<T> {\n return lastValueFrom(\n withDevicePolling(transportId)<T>((transport) => from(job(transport)), retryOnError),\n );\n }\n\n /* v8 ignore start */\n const noRetry = (): boolean => false;\n const alwaysRetry = (): boolean => true;\n /* v8 ignore stop */\n const poll = async (\n opts: { retryOnError?: RetryOnError } = {},\n ): Promise<{ isAppOpened: boolean }> => {\n // waiting for device to be turned on\n await run(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n async (_transport) => {},\n opts.retryOnError ?? alwaysRetry,\n );\n // checking if app is opened: should return directly on getPubKey\n try {\n await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });\n return { isAppOpened: true };\n } catch (err) {\n if (isTransportStatusError(err) && genericRetryOnError(err)) {\n return { isAppOpened: false };\n }\n throw err;\n }\n };\n\n const pollApp = async (appName: string): Promise<string> => {\n const res = await run((transport) =>\n transport.send(0xe0, 0xd8, 0x00, 0x00, Buffer.from(appName, \"utf8\")),\n );\n // little delay to give time to the app to be fully opened\n await new Promise((r) => setTimeout(r, 1e3));\n return res.toString(\"hex\");\n };\n\n const getPublicKey = async (\n pathString: string,\n { secp256k1, retryOnError }: { secp256k1: boolean; retryOnError?: RetryOnError },\n ): Promise<{ pubKey: string; signature: string }> => {\n logger.info(`[device] getPublicKey (${pathString})`);\n const path = getPathFromPathString(pathString);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const curve = secp256k1 ? 0x01 : 0x02;\n const response = await run(\n (transport) => transport.send(0xe0, 0x40, curve, 0x00, data),\n retryOnError ?? genericRetryOnError,\n );\n const pubKeyLength = response.readInt8(0);\n const pubKey = response\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = response\n .slice(pubKeyLength + 1, response.length - STATUS_LENGTH)\n .toString(\"base64\");\n return { pubKey, signature };\n };\n\n const device: Device = {\n authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {\n logger.info(`[device] Authenticate`);\n invariant(role !== \"READ_ONLY_API_KEY\", \"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n const nameBuffer = Buffer.from(name);\n const workspaceBuffer = Buffer.from(workspaceName);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([nameBuffer.length]),\n nameBuffer,\n Buffer.from([workspaceBuffer.length]),\n workspaceBuffer,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([\n Buffer.from(challenge, \"base64\"),\n applicationBuffer,\n Buffer.from([keyHandle.length]),\n Buffer.from(keyHandle, \"hex\"),\n keyHandleDataLength,\n keyHandleData,\n ]);\n\n const authentication = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x02, 0x00, 0x00], data),\n );\n\n return removeStatus(authentication).toString(\"hex\");\n },\n\n finalizePairingHandshake: async (params: {\n handshake: string;\n partitionId: string;\n handshakeAttestation: HsmCertificate;\n }): Promise<string> => {\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x47, 0x00, 0x02], buildAttestation(params)),\n );\n return removeStatus(bufWithStatus).toString(\"hex\");\n },\n\n generateSeedFragment: FIXME_NOT_IMPLEMENTED(\"generateSeedFragment\"),\n generateWrappingKeyFragment: FIXME_NOT_IMPLEMENTED(\"generateWrappingKeyFragment\"),\n getAttestation: async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x41, 0x00, 0x00));\n const buffer = removeStatus(bufWithStatus);\n const certLen = buffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: buffer.slice(0, 32).toString(\"base64\"),\n attestationPub: buffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer,\n };\n },\n getConfidentialityKey: async () => {\n logger.info(`[device] getConfidentialityKey`);\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x4d, 0x00, 0x00));\n const buf = removeStatus(bufWithStatus);\n const keyLength = buf[0]!;\n const key = buf.slice(1, 1 + keyLength);\n const sig = buf.slice(1 + keyLength + 1);\n return {\n confidentialityKeyCurve25519: key.toString(\"hex\"),\n confidentialityKeySignature: sig.toString(\"hex\"),\n };\n },\n getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),\n getDeviceUserId: FIXME_NOT_IMPLEMENTED(\"getDeviceUserId\"),\n getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),\n getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),\n hasPairing: async () => {\n logger.info(`[device] hasPairing`);\n const apdu = [0xe0, 0x51, 0x00, 0x00, 0xb5];\n const res = await run((transport) => transport.exchange(Buffer.from(apdu)));\n const hex = Buffer.from(res).toString(\"hex\");\n\n // 6f45 => this error means that there is no partition ID on the device\n // if no error, it means there is (at least) one\n //\n // 6a87 => TEMPORARY hack because Stax apparently does not implement\n // the \"get partition id\" APDU, so it returns \"incorrect length\"\n // easier to just assume that in this case there is no partition,\n // and try to insert one anyway (done on revault onboarding)\n //\n return hex !== \"6f45\" && hex !== \"6a87\";\n },\n\n initPairingHandshake: async (): Promise<{ pubKey: string; signature: string }> => {\n const res = await run((transport) => transport.send(0xe0, 0x46, 0x00, 0x00));\n const pubKeyLength = res.readInt8(0);\n const pubKey = res\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString(\"base64\");\n return { pubKey, signature };\n },\n\n openSession: FIXME_NOT_IMPLEMENTED(\"openSession\"),\n\n register: async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n invariant(applicationBuf.length === 32, \"application hex is expected to have 32 bytes\");\n\n const userNameBuff = Buffer.from(name);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([userNameBuff.length]),\n userNameBuff,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);\n\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x01, 0x00, 0x00], data),\n );\n\n let i = 0;\n const rfu = response.slice(i, (i += 1))[0]!;\n const pubKey = response.slice(i, (i += 65)).toString(\"hex\");\n const keyHandleLength = response.slice(i, ++i)[0]!;\n const keyHandle = response.slice(i, (i += keyHandleLength));\n return {\n u2fRegister: removeStatus(response),\n keyHandle,\n rfu,\n pubKey,\n };\n },\n registerData: async (params: { challenge: string }): Promise<string> => {\n const { challenge: strChallenge } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const response = await run((transport) => transport.send(0xe0, 0x03, 0x00, 0x00, challenge));\n return removeStatus(response).toString(\"hex\");\n },\n\n setPairing: async ({ pairing }) => {\n logger.info(`[device] setPairing`);\n const psdPayload = Buffer.from(pairing.blob, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(psdPayload.length, 0);\n const final = Buffer.concat([length, psdPayload]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x4e, 0x00, 0x00], final));\n },\n startKKPatternAsResponder: FIXME_NOT_IMPLEMENTED(\"startKKPatternAsResponder\"),\n startKPatternAsResponder: async (params) => {\n logger.info(`[device] startKPatternAsResponder`);\n const data = buildAttestation(params);\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x49, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n },\n validateVaultOperation: async (params) => {\n logger.info(`[device] validateVaultOperation`);\n const path = getPathFromPathString(PATHS.VALIDATION);\n const paths = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n let nextActionId = 1;\n let finalResponse;\n\n while (!finalResponse) {\n const screen = Buffer.from(params.actions[nextActionId - 1]!, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(screen.length, 0);\n const data = Buffer.concat([paths, length, screen]);\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x45, 0x00, 0x00], data),\n );\n const responseType = response.readInt8(0);\n let responseStatus = response.readUInt16BE(response.length - 2);\n if (responseType === STREAMING_NEXT_ACTION) {\n nextActionId = response.readUIntBE(1, 2);\n } else if (responseType === STREAMING_RESPONSE) {\n finalResponse = response.slice(3, response.length - 2);\n /* v8 ignore start */\n while (responseStatus !== 0x9000) {\n const resp = await run((transport) => transport.send(0x00, 0xc0, 0x00, 0x00));\n responseStatus = resp.readUInt16BE(resp.length - 2);\n finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);\n }\n } else {\n throw Error(`${responseType}`);\n }\n /* v8 ignore stop */\n }\n return finalResponse.toString(\"base64\");\n },\n\n sendAPDU: async (apduCommand: string) => {\n const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, \"hex\")));\n return Buffer.from(res).toString(\"hex\");\n },\n getVersion: async () => {\n const res = await run((transport) => transport.send(0xb0, 0x01, 0x00, 0x00));\n const appNameLen = res.readInt8(1);\n const appVersionLen = res.readInt8(2 + appNameLen);\n const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);\n\n const appVersion = Buffer.from(appVersionHex).toString();\n\n return appVersion;\n },\n poll,\n pollApp,\n };\n return device;\n}\n","import type { AppRouter } from \"@ledgerhq/revault-api\";\nimport { type TRPCClient, createTRPCClient, httpBatchLink } from \"@trpc/client\";\nimport type { inferRouterInputs, inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nexport type TRPCClientOptions = {\n baseUrl: string;\n debugAuthToken?: string;\n rootAuthToken?: string;\n apiAccessToken?: string;\n psdAuth?: string;\n};\n\nexport type RevaultApiTRPCClient = TRPCClient<AppRouter>;\n\nexport type RouterInputs = inferRouterInputs<AppRouter>;\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n\nexport const createClient = (options: TRPCClientOptions): RevaultApiTRPCClient => {\n const trpc = createTRPCClient<AppRouter>({\n links: [\n httpBatchLink({\n url: `${options.baseUrl}/trpc`,\n transformer: superjson,\n headers() {\n return {\n ...(options.debugAuthToken\n ? { \"x-revault-debug-auth-token\": options.debugAuthToken }\n : {}),\n ...(options.rootAuthToken\n ? { \"x-revault-root-auth-token\": options.rootAuthToken }\n : {}),\n ...(options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}),\n ...(options.apiAccessToken\n ? { Authorization: `Bearer ${options.apiAccessToken}` }\n : {}),\n };\n },\n }),\n ],\n });\n return trpc;\n};\n"]}
1
+ {"version":3,"sources":["/home/runner/_work/revault/revault/packages/sdk/lib/engine.cjs","../src/engine/index.ts","../src/device/real-device.ts","../src/trpc.ts"],"names":["withApiUser","withWorkspace","withOnboarding","client","engine"],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACA;ACLA,4FAAsB;ADOtB;AACA;AEpBA,0CAAsD;AAGtD;AACA,4BAAoC;AAkBpC,IAAM,iBAAA,EAAmB,GAAA;AAMzB,IAAM,sBAAA,EACJ,CAAC,MAAA,EAAA,GACD,MAAA,CAAA,EAAA,GAAY;AACV,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,MAAM,CAAA,CAAA;AAC5C;AAE8D;AACpB,EAAA;AACP,EAAA;AACrC;AAEiE;AAC/C,EAAA;AACyB,EAAA;AACF,IAAA;AACvC,EAAA;AACO,EAAA;AACT;AAE8D;AAK5D;AAG0C,EAAA;AACb,EAAA;AACW,EAAA;AAChB,IAAA;AACE,IAAA;AAGT,IAAA;AAE2B,IAAA;AACxC,MAAA;AACG,MAAA;AACJ,IAAA;AACH,EAAA;AACO,EAAA;AACT;AAMc;AACyB,EAAA;AACC,EAAA;AACA,EAAA;AAEA,EAAA;AACC,EAAA;AACC,EAAA;AAEH,EAAA;AAED,EAAA;AAClC,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACD,EAAA;AAEuC,EAAA;AACC,EAAA;AACV,EAAA;AAEM,EAAA;AACC,EAAA;AACA,EAAA;AAEC,EAAA;AACD,EAAA;AAEX,EAAA;AACzB,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACD,EAAA;AAEuC,EAAA;AACH,EAAA;AAEP,EAAA;AAEvB,EAAA;AACT;AAImD;AAEX,EAAA;AAEC,EAAA;AAEA,EAAA;AAGhC,EAAA;AACT;AAG2E;AACjD,EAAA;AAIO,EAAA;AAEtB,IAAA;AAC8B,MAAA;AACrC,IAAA;AACF,EAAA;AAG+B,EAAA;AACI,EAAA;AAIK,EAAA;AAEhC,IAAA;AAAA;AAEkB,MAAA;AAAC,MAAA;AACF,uBAAA;AACvB,IAAA;AAEI,IAAA;AAC8B,MAAA;AACL,MAAA;AACf,IAAA;AACuB,MAAA;AACL,QAAA;AAC9B,MAAA;AACM,MAAA;AACR,IAAA;AACF,EAAA;AAE4D,EAAA;AACxC,IAAA;AACK,MAAA;AACvB,IAAA;AAEuC,IAAA;AACd,IAAA;AAC3B,EAAA;AAII,EAAA;AAEoC,IAAA;AACH,IAAA;AACR,IAAA;AACA,MAAA;AACG,MAAA;AACA,QAAA;AACK,QAAA;AACxB,QAAA;AACR,MAAA;AACF,IAAA;AACgC,IAAA;AACV,IAAA;AACqB,MAAA;AAC1B,uBAAA;AAClB,IAAA;AACwC,IAAA;AAE5B,IAAA;AAIH,IAAA;AAEkB,IAAA;AAC7B,EAAA;AAEuB,EAAA;AACe,IAAA;AACC,MAAA;AAChB,MAAA;AACmB,MAAA;AACH,MAAA;AACC,MAAA;AAEA,MAAA;AACA,QAAA;AACH,QAAA;AAC/B,QAAA;AACoC,QAAA;AACpC,QAAA;AACD,MAAA;AAEkC,MAAA;AACD,MAAA;AAEP,MAAA;AACM,QAAA;AAC/B,QAAA;AAC8B,QAAA;AACF,QAAA;AAC5B,QAAA;AACA,QAAA;AACD,MAAA;AAE4B,MAAA;AACf,QAAA;AACd,MAAA;AAEoC,MAAA;AACtC,IAAA;AAEiC,IAAA;AAKH,MAAA;AACd,QAAA;AACd,MAAA;AACmC,MAAA;AACrC,IAAA;AAEsB,IAAA;AACO,IAAA;AAQvB,IAAA;AAC6B,MAAA;AACL,MAAA;AACS,MAAA;AAC9B,MAAA;AACQ,QAAA;AACmB,UAAA;AACG,UAAA;AACE,UAAA;AACrC,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACmC,IAAA;AACrB,MAAA;AACqB,MAAA;AACK,MAAA;AACf,MAAA;AACe,MAAA;AACC,MAAA;AAChC,MAAA;AAC6B,QAAA;AACD,QAAA;AACnC,MAAA;AACF,IAAA;AACgC,IAAA;AACO,IAAA;AACA,IAAA;AACC,IAAA;AAChB,IAAA;AACW,MAAA;AACS,MAAA;AACL,MAAA;AACC,MAAA;AAUL,MAAA;AACnC,IAAA;AAEkF,IAAA;AAC3C,MAAA;AACF,MAAA;AAEvB,MAAA;AAGgB,MAAA;AACD,MAAA;AAC7B,IAAA;AAEmC,IAAA;AAY7B,IAAA;AAC6B,MAAA;AACH,MAAA;AAEK,MAAA;AACA,MAAA;AACC,MAAA;AAEC,MAAA;AAED,MAAA;AACA,QAAA;AACD,QAAA;AACjC,QAAA;AACD,MAAA;AAEkC,MAAA;AACD,MAAA;AAEK,MAAA;AAEhB,MAAA;AACT,QAAA;AACd,MAAA;AAEQ,MAAA;AACiC,MAAA;AACF,MAAA;AACA,MAAA;AACF,MAAA;AAC9B,MAAA;AAC6B,QAAA;AAClC,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACwE,IAAA;AAClC,MAAA;AACN,MAAA;AACK,MAAA;AACP,MAAA;AACW,MAAA;AACzC,IAAA;AAEmC,IAAA;AACA,MAAA;AACM,MAAA;AACV,MAAA;AACG,MAAA;AACK,MAAA;AACA,MAAA;AACvC,IAAA;AAC2B,IAAA;AACM,IAAA;AACnB,MAAA;AACwB,MAAA;AAC9B,MAAA;AACQ,QAAA;AACd,MAAA;AACF,IAAA;AAC+B,IAAA;AACjB,MAAA;AACuB,MAAA;AACP,MAAA;AACD,QAAA;AACG,QAAA;AACA,UAAA;AACK,UAAA;AACxB,UAAA;AACR,QAAA;AACF,MAAA;AAEkB,MAAA;AACf,MAAA;AAEmB,MAAA;AACa,QAAA;AACL,QAAA;AACQ,QAAA;AACF,QAAA;AACZ,QAAA;AACT,UAAA;AACd,QAAA;AAC8B,QAAA;AACA,QAAA;AACT,QAAA;AACgB,UAAA;AACT,QAAA;AACQ,UAAA;AAEA,UAAA;AACR,YAAA;AACF,YAAA;AACS,YAAA;AACjC,UAAA;AACK,QAAA;AACwB,UAAA;AAC/B,QAAA;AAEF,MAAA;AACsC,MAAA;AACxC,IAAA;AAEyC,IAAA;AACF,MAAA;AACC,MAAA;AACxC,IAAA;AACwB,IAAA;AACe,MAAA;AACJ,MAAA;AACM,MAAA;AACH,MAAA;AAEL,MAAA;AAExB,MAAA;AACT,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACO,EAAA;AACT;AFzH6C;AACA;AGnVe;AAEtC;AAe4D;AACvC,EAAA;AAChC,IAAA;AACI,MAAA;AACgB,QAAA;AACV,QAAA;AACH,QAAA;AACD,UAAA;AAEC,YAAA;AAGA,YAAA;AAEkB,YAAA;AAElB,YAAA;AAER,UAAA;AACF,QAAA;AACD,MAAA;AACH,IAAA;AACD,EAAA;AACM,EAAA;AACT;AHgU6C;AACA;AC/TX;AAChC,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AAaa;AACkB,EAAA;AACP,IAAA;AACF,IAAA;AACY,IAAA;AACjC,EAAA;AACoC,EAAA;AACU,EAAA;AAC7C,IAAA;AACkB,IAAA;AACR,IAAA;AAC6B,IAAA;AACN,IAAA;AACL,IAAA;AACX,MAAA;AACY,MAAA;AAC7B,IAAA;AACF,EAAA;AACuC,EAAA;AACH,EAAA;AACb,IAAA;AACE,IAAA;AACS,IAAA;AACjC,EAAA;AACsC,EAAA;AAChB,IAAA;AACM,IAAA;AAC3B,IAAA;AACA,IAAA;AACD,EAAA;AACqC,EAAA;AACJ,EAAA;AACM,EAAA;AACN,EAAA;AACF,IAAA;AACS,IAAA;AAC3B,IAAA;AACe,IAAA;AACZ,EAAA;AAC4C,EAAA;AAC3D,IAAA;AACa,IAAA;AACI,MAAA;AACa,MAAA;AAC9B,IAAA;AACA,IAAA;AACiC,IAAA;AACD,IAAA;AAChC,IAAA;AACF,EAAA;AAC2C,EAAA;AAC7C;AAE6E;AAClC,EAAA;AACtB,IAAA;AACnB,EAAA;AACyC,EAAA;AACE,EAAA;AAElB,EAAA;AACvB,IAAA;AAC6B,IAAA;AAC/B,EAAA;AAIE,EAAA;AAEyC,IAAA;AACJ,IAAA;AACD,IAAA;AACtC,EAAA;AAIE,EAAA;AAEkC,IAAA;AACG,IAAA;AACD,IAAA;AACtC,EAAA;AAEyE,EAAA;AAClB,IAAA;AACjBA,IAAAA;AACtC,EAAA;AAIE,EAAA;AAEuC,IAAA;AACHC,IAAAA;AACtC,EAAA;AAIE,EAAA;AAEyC,IAAA;AACLC,IAAAA;AACtC,EAAA;AASa,EAAA;AAGH,IAAA;AAC2D,MAAA;AACnE,IAAA;AAImB,IAAA;AACjB,MAAA;AAEK,QAAA;AAC+C,UAAA;AACrB,YAAA;AACS,YAAA;AACCC,YAAAA;AAC1B,YAAA;AACT,UAAA;AACF,QAAA;AACJ,MAAA;AACF,IAAA;AAIsC,IAAA;AACyC,MAAA;AAC/CC,QAAAA;AACrB,QAAA;AAC+E,UAAA;AAC/C,YAAA;AAChB,YAAA;AACG,YAAA;AACW,YAAA;AACnC,UAAA;AACF,QAAA;AACD,MAAA;AACH,IAAA;AAI4B,IAAA;AACyD,MAAA;AACzD,QAAA;AACuB,QAAA;AACd,UAAA;AACZ,UAAA;AACG,YAAA;AACS,YAAA;AAC9B,UAAA;AAC4B,UAAA;AAC3B,YAAA;AACc,YAAA;AACR,YAAA;AAC0B,cAAA;AACD,cAAA;AAC/B,YAAA;AACD,UAAA;AACkC,UAAA;AACrC,QAAA;AACO,QAAA;AACoF,UAAA;AAC1D,YAAA;AACA,YAAA;AACP,cAAA;AACb,cAAA;AACR,YAAA;AACuB,YAAA;AACR,cAAA;AACS,cAAA;AACxB,YAAA;AACH,UAAA;AAEmC,UAAA;AACd,YAAA;AACG,cAAA;AACb,cAAA;AACR,YAAA;AACwB,YAAA;AACR,cAAA;AACO,gBAAA;AACK,gBAAA;AAC3B,cAAA;AACD,YAAA;AAC6B,YAAA;AACJ,YAAA;AACF,YAAA;AACtB,cAAA;AACc,cAAA;AACJ,cAAA;AACR,gBAAA;AACiB,gBAAA;AACK,gBAAA;AACjB,kBAAA;AACQ,kBAAA;AACb,gBAAA;AACF,cAAA;AACD,YAAA;AACH,UAAA;AAEiF,UAAA;AACxD,YAAA;AAErB,YAAA;AAIA,YAAA;AAGoB,YAAA;AACpB,cAAA;AACA,cAAA;AACA,cAAA;AACyB,cAAA;AAEP,gBAAA;AACd,gBAAA;AACA,gBAAA;AACD,cAAA;AACyB,cAAA;AAEH,gBAAA;AACrB,gBAAA;AAAA;AAEU,gBAAA;AACX,cAAA;AACJ,YAAA;AACH,UAAA;AAE0B,UAAA;AACH,YAAA;AACW,YAAA;AACnB,YAAA;AACU,cAAA;AACC,cAAA;AACC,cAAA;AACxB,YAAA;AAC8B,YAAA;AACV,cAAA;AACpB,YAAA;AACuB,YAAA;AACR,cAAA;AACd,cAAA;AACA,cAAA;AACD,YAAA;AACH,UAAA;AAE4B,UAAA;AACL,YAAA;AACY,YAAA;AACX,cAAA;AACE,cAAA;AACvB,YAAA;AACY,YAAA;AACU,cAAA;AACC,cAAA;AACC,cAAA;AACxB,YAAA;AAC+B,YAAA;AACX,cAAA;AACpB,YAAA;AAC8B,YAAA;AACN,cAAA;AACF,cAAA;AACC,cAAA;AACvB,YAAA;AAC0B,YAAA;AACH,YAAA;AACR,cAAA;AACd,cAAA;AACc,cAAA;AACZ,gBAAA;AACA,gBAAA;AACqB,gBAAA;AACC,gBAAA;AACjB,kBAAA;AACkB,kBAAA;AACvB,gBAAA;AACF,cAAA;AACD,YAAA;AACH,UAAA;AACF,QAAA;AACD,MAAA;AACH,IAAA;AAI4B,IAAA;AAC1B,MAAA;AACc,QAAA;AACc,UAAA;AACjB,UAAA;AAI+B,YAAA;AACT,cAAA;AACDD,cAAAA;AACtB,gBAAA;AACe,gBAAA;AAChB,cAAA;AACyB,8BAAA;AACG,cAAA;AAC3B,gBAAA;AACe,gBAAA;AAChB,cAAA;AACmB,cAAA;AACH,gBAAA;AACf,gBAAA;AACA,gBAAA;AAC4B,gBAAA;AAC9B,cAAA;AACwBA,cAAAA;AACS,cAAA;AACnB,gBAAA;AACd,cAAA;AAC0B,cAAA;AACE,cAAA;AACD,cAAA;AAG7B,YAAA;AAIwC,YAAA;AACf,cAAA;AACrB,gBAAA;AACmB,gBAAA;AACA,gBAAA;AACI,gBAAA;AACGA,kBAAAA;AACL,oBAAA;AACF,oBAAA;AACf,oBAAA;AACD,kBAAA;AACM,kBAAA;AACT,gBAAA;AACoB,gBAAA;AAED,kBAAA;AACE,kBAAA;AACjB,kBAAA;AACD,gBAAA;AACJ,cAAA;AACH,YAAA;AACF,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAIqC,IAAA;AACnC,MAAA;AACc,QAAA;AACM,UAAA;AACT,UAAA;AAGH,YAAA;AAK8B,cAAA;AACN,gBAAA;AACI,gBAAA;AACf,gBAAA;AACZ,cAAA;AACgC,cAAA;AACpB,gBAAA;AACb,cAAA;AAC4B,cAAA;AACD,cAAA;AAG7B,YAAA;AACF,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAI4B,IAAA;AAC8D,MAAA;AAC3DC,QAAAA;AAEoB,QAAA;AACd,UAAA;AACE,UAAA;AACJ,UAAA;AACG,YAAA;AACD,YAAA;AAC9B,UAAA;AACkC,UAAA;AACrC,QAAA;AAEO,QAAA;AAGH,UAAA;AAE4BD,YAAAA;AACR,YAAA;AACC,YAAA;AACR,YAAA;AACU,cAAA;AACC,cAAA;AACC,cAAA;AACxB,YAAA;AAC2B,4BAAA;AACG,YAAA;AACV,cAAA;AACpB,YAAA;AAC8B,YAAA;AACjB,cAAA;AACkB,cAAA;AAC/B,YAAA;AACH,UAAA;AAE0E,UAAA;AAC1C,YAAA;AAChC,UAAA;AACF,QAAA;AACD,MAAA;AACH,IAAA;AAIqC,IAAA;AACsD,MAAA;AACpEC,QAAAA;AACZ,QAAA;AACoF,UAAA;AAC3DD,YAAAA;AACR,YAAA;AACH,YAAA;AACnB,UAAA;AAKoC,UAAA;AACH,YAAA;AACjB,cAAA;AACkB,cAAA;AAC/B,YAAA;AACH,UAAA;AAKoC,UAAA;AACJ,YAAA;AAChB,cAAA;AACkB,cAAA;AAC/B,YAAA;AACH,UAAA;AACF,QAAA;AACD,MAAA;AACH,IAAA;AAEO,IAAA;AACT,EAAA;AAEO,EAAA;AACF,IAAA;AACH,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACF;ADqN6C;AACA;AACA;AACA","file":"/home/runner/_work/revault/revault/packages/sdk/lib/engine.cjs","sourcesContent":[null,"import type {\n ApiChallenge,\n ClaimedRole,\n OnboardingSeedChallenge,\n PsdChallenge,\n UserRegistrationChallenge,\n UserRegistrationChallengeResponse,\n UserRegistrationDeviceData,\n UserRegistrationResponse,\n VaultRequestResponse,\n WrappingKeyResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport { type Device, createApiDevice } from \"@/device\";\nimport { createRealDevice } from \"@/device/real-device\";\nimport { type TRPCClientOptions, createClient } from \"@/trpc\";\nimport type { Logger } from \"@/types\";\n\nimport type {\n ApproveRequestParams,\n DecorateWithApiUserAndWorkspaceUnauthenticated,\n DecorateWithDevice,\n DecorateWithDeviceAndOnboarding,\n DecorateWithDeviceAndWorkspaceUnauthenticated,\n DecorateWithWorkspaceApiAuthenticated,\n DecorateWithWorkspacePsdAuthenticated,\n DecorateWithWorkspaceUnauthenticated,\n Engine,\n EngineBase,\n EngineOptions,\n RegisterOnboardingDeviceParams,\n WithApiAuth,\n WithApiUser,\n WithDevice,\n WithOnboarding,\n WithPsdAuth,\n WithWorkspace,\n} from \"./types\";\n\nexport { fetchAll } from \"../utils\";\n\nexport type * from \"./types\";\n\nasync function genericRegister<T>({\n device,\n name,\n role,\n getChallenge,\n submitChallenge,\n}: {\n device: Device;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n getChallenge: (p: {\n pubKey: string;\n deviceData: UserRegistrationDeviceData;\n }) => Promise<UserRegistrationChallenge>;\n submitChallenge: (p: {\n pubKey: string;\n challengeResponse: UserRegistrationChallengeResponse;\n }) => Promise<T>;\n}): Promise<T> {\n const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([\n device.getAttestation(),\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n const ephemeralPubKey = await device.initPairingHandshake();\n const deviceData: UserRegistrationDeviceData = {\n name,\n pubKey: u2fPubKey.pubKey,\n psdModel: \"STAX\",\n confidentialityKey: confidentialityKey.pubKey,\n psdEphemeralKey: ephemeralPubKey.pubKey,\n psdEphemeralKeyAttestation: {\n ...attestation.attestation,\n signature: ephemeralPubKey.signature,\n },\n };\n const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });\n const pairingPayload = await device.finalizePairingHandshake({\n handshake: challenge.handshake,\n partitionId: challenge.ciphertext,\n handshakeAttestation: challenge.handshakeAttestation,\n });\n const register = await device.register({\n challenge: challenge.challenge,\n u2fRegisterData: challenge.u2fRegisterData,\n name,\n role,\n });\n const validationPubKey = await device.getValidationPubKey();\n const registerData = await device.registerData({ challenge: challenge.challenge });\n const attestationOffset = 67 + register.u2fRegister.readInt8(66);\n const u2fRegister = Buffer.concat([\n register.u2fRegister.slice(0, attestationOffset),\n Buffer.from([attestation.buffer.length]),\n attestation.buffer,\n register.u2fRegister.slice(attestationOffset),\n ]).toString(\"hex\");\n const challengeResponse: UserRegistrationChallengeResponse = {\n registerData,\n certificate: {\n ...attestation.attestation,\n signature: validationPubKey.signature,\n },\n u2fRegister,\n u2fKeyHandle: register.keyHandle.toString(\"hex\"),\n validationKey: validationPubKey.pubKey,\n pairingPayload,\n };\n return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });\n}\n\nexport function createEngine(options: EngineOptions, logger: Logger): Engine {\n const clientOptions: TRPCClientOptions = {\n baseUrl: options.baseUrl,\n };\n const client = createClient(clientOptions);\n const apiDevice = createApiDevice(options, logger);\n\n const base: EngineBase = {\n client,\n createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),\n };\n\n const withDeviceIndex: Engine[\"withDeviceIndex\"] = function <T>(\n this: Engine<T>,\n deviceIndex: number,\n ) {\n const device = apiDevice.with(deviceIndex);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withTransportId: Engine[\"withTransportId\"] = function <T>(\n this: Engine<T>,\n transportId: string,\n ) {\n const device = createRealDevice({ transportId }, logger);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withApiUser: Engine[\"withApiUser\"] = function <T>(this: Engine<T>) {\n const withApiUser: WithApiUser = { __isApiUser: true };\n return decorateEngine({ ...this, ...withApiUser } as Engine<T & WithApiUser>);\n };\n\n const withWorkspace: Engine[\"withWorkspace\"] = function <T>(\n this: Engine<T>,\n workspaceName: string,\n ) {\n const withWorkspace: WithWorkspace = { __workspaceName: workspaceName };\n return decorateEngine({ ...this, ...withWorkspace } as Engine<T & WithWorkspace>);\n };\n\n const withOnboarding: Engine[\"withOnboarding\"] = function <T>(\n this: Engine<T>,\n onboardingId: string,\n ) {\n const withOnboarding: WithOnboarding = { __onboardingId: onboardingId };\n return decorateEngine({ ...this, ...withOnboarding } as Engine<T & WithOnboarding>);\n };\n\n function decorateEngine<T>(\n engine: Engine<\n T &\n Partial<\n WithDevice & WithOnboarding & WithWorkspace & WithPsdAuth & WithApiUser & WithApiAuth\n >\n >,\n ): Engine<T> {\n function decorate<TEnhanced, TDecoration>(\n decorator: (engine: EngineBase & TEnhanced) => TDecoration,\n ): void {\n Object.assign(engine, decorator(engine as EngineBase & TEnhanced));\n }\n\n // DecorateWithDevice\n // -------------------------------------------------------------------------\n if (engine.device) {\n decorate<WithDevice, DecorateWithDevice<T>>(\n (engine) =>\n ({\n getWorkspaces: async (): Promise<string[]> => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });\n return workspaceNames;\n },\n }) satisfies DecorateWithDevice<T>,\n );\n }\n\n // DecorateWithWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {\n decorate<WithWorkspace, DecorateWithWorkspaceUnauthenticated<T>>((engine) => {\n const { __workspaceName } = engine;\n return {\n withPsdToken: function <T>(this: Engine<T>, token: string): Engine<T & WithPsdAuth> {\n const withPsdAuth: WithPsdAuth = { __psdToken: token };\n const psdAuth = `${__workspaceName}:${token}`;\n const client = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client, ...withPsdAuth } as Engine<T & WithPsdAuth>);\n },\n } satisfies DecorateWithWorkspaceUnauthenticated<T>;\n });\n }\n\n // DecorateWithDeviceAndOnboarding\n // -------------------------------------------------------------------------\n if (engine.device && engine.__onboardingId) {\n decorate<WithDevice & WithOnboarding, DecorateWithDeviceAndOnboarding>((engine) => {\n const { device, client, __onboardingId } = engine;\n async function enforcePairing(): Promise<void> {\n if (await device.hasPairing()) return;\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityKey(),\n ]);\n const pairing = await client.onboarding.pairDevicePartition.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data: {\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n },\n });\n await device.setPairing({ pairing });\n }\n return {\n claimDevice: async (params: { role: ClaimedRole; deviceName: string }): Promise<void> => {\n const { role, deviceName } = params;\n const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await client.onboarding.claimDevice.mutate({\n onboardingId: __onboardingId,\n claim: { role, pubKey, deviceName, confidentialityKey },\n });\n },\n\n collectWrappingKeyFragment: async (wrappingKey: WrappingKeyResponse): Promise<void> => {\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await device.openSession({\n secureChannel: {\n pubKey: wrappingKey.ephemeralPubKey,\n certificate: wrappingKey.ephemeralCertificate,\n },\n });\n const { attestation } = await device.getAttestation();\n const blob = await device.generateWrappingKeyFragment();\n await client.onboarding.submitWrappingKeyFragment.mutate({\n pubKey,\n onboardingId: __onboardingId,\n fragment: {\n blob,\n ephemeralPubKey: confidentialityKey.pubKey,\n ephemeralCertificate: {\n ...attestation,\n signature: confidentialityKey.signature,\n },\n },\n });\n },\n\n registerDevice: async (params: RegisterOnboardingDeviceParams): Promise<void> => {\n const { role, name } = params;\n const getChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.generateMasterAdminRegistrationChallenge\n : client.onboarding.generateSharedOwnerRegistrationChallenge;\n const submitChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.submitMasterAdminRegistration\n : client.onboarding.submitSharedOwnerRegistration;\n await genericRegister({\n device: device,\n name,\n role,\n getChallenge: ({ pubKey, deviceData }) =>\n getChallengeMutation.mutate({\n onboardingId: __onboardingId,\n pubKey,\n deviceData,\n }),\n submitChallenge: ({ pubKey, challengeResponse }) =>\n submitChallengeMutation.mutate({\n onboardingId: engine.__onboardingId,\n pubKey,\n // FIXME this should be renamed to `challengeResponse` on backend side\n response: challengeResponse,\n }),\n });\n },\n\n reviewSharedOwner: async (challenge: PsdChallenge): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitReviewByMasterAdminSignature.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n collectSeedFragment: async (challenge: OnboardingSeedChallenge): Promise<void> => {\n await enforcePairing();\n const [{ pubKey }, { attestation }] = await Promise.all([\n device.getU2FPubKey(),\n device.getAttestation(),\n ]);\n await device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n const challengeResponse = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n const kkPattern = await device.startKKPatternAsResponder({\n partitionId: challenge.partitionId,\n handshake: challenge.kkHandshake,\n handshakeAttestation: challenge.kkHandshakeAttestation,\n });\n const approverBlob = await device.generateSeedFragment();\n await client.onboarding.submitSeedFragment.mutate({\n onboardingId: __onboardingId,\n pubKey,\n seedFragment: {\n challengeResponse,\n approverBlob,\n handshake: kkPattern.handshake,\n handshakeAttestation: {\n ...attestation,\n signature: kkPattern.signature,\n },\n },\n });\n },\n } satisfies DecorateWithDeviceAndOnboarding;\n });\n }\n\n // DecorateWithDeviceAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && !engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithDeviceAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { device, client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n opts?: { validityDurationSecs?: number; onScreenDisplayed?: () => void },\n ): Promise<Engine<T & WithPsdAuth>> {\n const { pubKey } = await device.getU2FPubKey();\n const challenge = await client.auth.psd.generateChallenge.mutate({\n pubKey,\n workspaceName: __workspaceName,\n });\n opts?.onScreenDisplayed?.();\n const authentication = await device.authenticate({\n challenge,\n workspaceName: __workspaceName,\n });\n const authPayload = {\n workspaceName: __workspaceName,\n pubKey,\n authentication,\n validityDurationSecs: opts?.validityDurationSecs,\n };\n const { token } = await client.auth.psd.authenticate.mutate({ ...authPayload });\n const withPsdAuth: WithPsdAuth = {\n __psdToken: token,\n };\n const psdAuth = `${engine.__workspaceName}:${token}`;\n const __authClient = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client: __authClient, ...withPsdAuth } as Engine<\n T & WithPsdAuth\n >);\n },\n\n register: (\n registration: UserRegistrationResponse,\n ): Promise<UserRegistrationResponse> => {\n return genericRegister({\n device,\n name: registration.name,\n role: registration.role,\n getChallenge: async ({ deviceData }) => {\n const challenge = await client.userRegistrations.generateChallenge.mutate({\n id: registration.id,\n workspaceName: __workspaceName,\n deviceData,\n });\n return challenge;\n },\n submitChallenge: ({ challengeResponse }) =>\n client.userRegistrations.submitChallenge.mutate({\n workspaceName: __workspaceName,\n id: registration.id,\n challengeResponse,\n }),\n });\n },\n } satisfies DecorateWithDeviceAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithApiUserAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {\n decorate<WithWorkspace & WithApiUser, DecorateWithApiUserAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n credentials: {\n apiKeyId: string;\n apiKeySecret: string;\n },\n ): Promise<Engine<T & WithApiAuth>> {\n const res = await client.auth.authenticate.mutate({\n apiKeyId: credentials.apiKeyId,\n apiKeySecret: credentials.apiKeySecret,\n workspace: __workspaceName,\n });\n const withApiAuth: WithApiAuth = {\n __apiAuth: res,\n };\n const __authClient = engine.createClient({ apiAccessToken: res.accessToken });\n return decorateEngine({ ...this, client: __authClient, ...withApiAuth } as Engine<\n T & WithApiAuth\n >);\n },\n } satisfies DecorateWithApiUserAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithWorkspacePsdAuthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithWorkspacePsdAuthenticated>((engine) => {\n const { client, device } = engine;\n\n async function enforcePairing(): Promise<void> {\n if (await device.hasPairing()) return;\n const confidentialityKey = await device.getConfidentialityKey();\n const pairing = await client.debug.pairDevicePartition.mutate({\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n });\n await device.setPairing({ pairing });\n }\n\n return {\n approve: async (\n request: VaultRequestResponse,\n params?: ApproveRequestParams,\n ): Promise<VaultRequestResponse> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"PSD\", \"Challenge type must be PSD\");\n await enforcePairing();\n await device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"PSD\", signature },\n });\n },\n\n reject: (request: VaultRequestResponse): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({ id: request.id, data: null });\n },\n } satisfies DecorateWithWorkspacePsdAuthenticated;\n });\n }\n\n // DecorateWithWorkspaceApiAuthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__apiAuth) {\n decorate<WithWorkspace & WithApiAuth, DecorateWithWorkspaceApiAuthenticated>((engine) => {\n const { client } = engine;\n return {\n getChallenge: async (request: VaultRequestResponse): Promise<ApiChallenge[\"payload\"]> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"API\", \"Challenge type must be API\");\n return challenge.payload;\n },\n\n approve: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n\n reject: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n } satisfies DecorateWithWorkspaceApiAuthenticated;\n });\n }\n\n return engine;\n }\n\n return {\n ...base,\n withDeviceIndex,\n withTransportId,\n withApiUser,\n withWorkspace,\n withOnboarding,\n };\n}\n","import { DisconnectedDevice, LockedDeviceError } from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport type { HsmCertificate } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { from, lastValueFrom } from \"rxjs\";\n\nimport type { Logger } from \"@/types\";\n\nimport {\n APPID_VAULT_ADMINISTRATOR,\n PAGINATED_STATUS,\n PATHS,\n SCRIPT_IDS,\n STATUS_LENGTH,\n STREAMING_NEXT_ACTION,\n STREAMING_RESPONSE,\n STR_ROLES,\n} from \"./constants\";\nimport { withDevicePolling } from \"./device-access\";\nimport type { Device } from \"./types\";\nimport { isTransportStatusError } from \"./utils\";\n\nconst MAX_CHUNK_LENGTH = 250;\n\ntype Options = {\n transportId: string;\n};\n\nconst FIXME_NOT_IMPLEMENTED =\n (fnName: string): (() => Promise<never>) =>\n async () => {\n throw new Error(`Not implemented: ${fnName}`);\n };\n\nconst getPathFromPathString = (pathString: string): number[] => {\n const parts = pathString.split(\"'/\").map((part) => parseInt(part, 10));\n return parts.map((part) => (part | 0x80000000) >>> 0);\n};\n\nconst splitChunks = (chunk: number, buffer: Buffer): Buffer[] => {\n const chunks = [];\n for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {\n chunks.push(buffer.slice(i, i + size));\n }\n return chunks;\n};\n\nconst removeStatus = (result: Buffer): Buffer => result.slice(0, result.length - STATUS_LENGTH);\n\nconst sendByChunk = async (\n transport: Transport,\n command: number[], // eg [0xe0, 0x45, 0x00, 0x00]\n data: Buffer,\n chunkSize: number = MAX_CHUNK_LENGTH,\n): Promise<Buffer> => {\n const chunks = splitChunks(chunkSize, data);\n let response = Buffer.from([]);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const apdu = [...command];\n // command is 0xe0,0x45,0x00,0x00 for first chunk, then it's 0xe0,0x45,0x80,0x00\n /* v8 ignore start */\n apdu[2] = i && 0x80;\n /* v8 ignore stop */\n response = await transport.send(apdu[0]!, apdu[1]!, apdu[2], apdu[3]!, chunk, [\n 0x9000,\n ...PAGINATED_STATUS,\n ]);\n }\n return response;\n};\n\nconst buildAttestation = (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n}): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const cliMsgBuffer = Buffer.from(params.handshake, \"hex\");\n const cliMsgLengthBuffer = Buffer.alloc(1);\n cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);\n\n const pidBuffer = Buffer.from(params.partitionId, \"hex\");\n const pidLengthBuffer = Buffer.alloc(1);\n pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n cliMsgLengthBuffer,\n cliMsgBuffer,\n certChainDataLengthBuff,\n certChainData,\n pidLengthBuffer,\n pidBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n const toSend = Buffer.concat([totalLengthBuffer, data]);\n\n return toSend;\n};\n\ntype RetryOnError = (err: Error) => boolean;\n/* v8 ignore start */\nconst genericRetryOnError: RetryOnError = (err) => {\n // device is locked\n if (err instanceof LockedDeviceError) return true;\n // user is on dashboard when receiving a Vault app apdu\n if (isTransportStatusError(err) && err.statusCode === 0x6d09) return true;\n // VG-24797 error that can happen in BLE in some situations (still unclear)\n if (err instanceof DisconnectedDevice) return true;\n\n // for everything else, we don't want to retry\n return false;\n};\n/* v8 ignore stop */\n\nexport function createRealDevice(options: Options, logger: Logger): Device {\n const { transportId } = options;\n\n async function run<T>(\n job: (transport: Transport) => Promise<T>,\n retryOnError: RetryOnError = genericRetryOnError,\n ): Promise<T> {\n return lastValueFrom(\n withDevicePolling(transportId)<T>((transport) => from(job(transport)), retryOnError),\n );\n }\n\n /* v8 ignore start */\n const noRetry = (): boolean => false;\n const alwaysRetry = (): boolean => true;\n /* v8 ignore stop */\n const poll = async (\n opts: { retryOnError?: RetryOnError } = {},\n ): Promise<{ isAppOpened: boolean }> => {\n // waiting for device to be turned on\n await run(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n async (_transport) => {},\n opts.retryOnError ?? alwaysRetry,\n );\n // checking if app is opened: should return directly on getPubKey\n try {\n await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });\n return { isAppOpened: true };\n } catch (err) {\n if (isTransportStatusError(err) && genericRetryOnError(err)) {\n return { isAppOpened: false };\n }\n throw err;\n }\n };\n\n const pollApp = async (appName: string): Promise<string> => {\n const res = await run((transport) =>\n transport.send(0xe0, 0xd8, 0x00, 0x00, Buffer.from(appName, \"utf8\")),\n );\n // little delay to give time to the app to be fully opened\n await new Promise((r) => setTimeout(r, 1e3));\n return res.toString(\"hex\");\n };\n\n const getPublicKey = async (\n pathString: string,\n { secp256k1, retryOnError }: { secp256k1: boolean; retryOnError?: RetryOnError },\n ): Promise<{ pubKey: string; signature: string }> => {\n logger.info(`[device] getPublicKey (${pathString})`);\n const path = getPathFromPathString(pathString);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const curve = secp256k1 ? 0x01 : 0x02;\n const response = await run(\n (transport) => transport.send(0xe0, 0x40, curve, 0x00, data),\n retryOnError ?? genericRetryOnError,\n );\n const pubKeyLength = response.readInt8(0);\n const pubKey = response\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = response\n .slice(pubKeyLength + 1, response.length - STATUS_LENGTH)\n .toString(\"base64\");\n return { pubKey, signature };\n };\n\n const device: Device = {\n authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {\n logger.info(`[device] Authenticate`);\n invariant(role !== \"READ_ONLY_API_KEY\", \"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n const nameBuffer = Buffer.from(name);\n const workspaceBuffer = Buffer.from(workspaceName);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([nameBuffer.length]),\n nameBuffer,\n Buffer.from([workspaceBuffer.length]),\n workspaceBuffer,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([\n Buffer.from(challenge, \"base64\"),\n applicationBuffer,\n Buffer.from([keyHandle.length]),\n Buffer.from(keyHandle, \"hex\"),\n keyHandleDataLength,\n keyHandleData,\n ]);\n\n const authentication = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x02, 0x00, 0x00], data),\n );\n\n return removeStatus(authentication).toString(\"hex\");\n },\n\n finalizePairingHandshake: async (params: {\n handshake: string;\n partitionId: string;\n handshakeAttestation: HsmCertificate;\n }): Promise<string> => {\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x47, 0x00, 0x02], buildAttestation(params)),\n );\n return removeStatus(bufWithStatus).toString(\"hex\");\n },\n\n generateSeedFragment: FIXME_NOT_IMPLEMENTED(\"generateSeedFragment\"),\n generateWrappingKeyFragment: FIXME_NOT_IMPLEMENTED(\"generateWrappingKeyFragment\"),\n getAttestation: async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x41, 0x00, 0x00));\n const buffer = removeStatus(bufWithStatus);\n const certLen = buffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: buffer.slice(0, 32).toString(\"base64\"),\n attestationPub: buffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer,\n };\n },\n getConfidentialityKey: async () => {\n logger.info(`[device] getConfidentialityKey`);\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x4d, 0x00, 0x00));\n const buf = removeStatus(bufWithStatus);\n const keyLength = buf[0]!;\n const key = buf.slice(1, 1 + keyLength);\n const sig = buf.slice(1 + keyLength + 1);\n return {\n confidentialityKeyCurve25519: key.toString(\"hex\"),\n confidentialityKeySignature: sig.toString(\"hex\"),\n };\n },\n getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),\n getDeviceUserId: FIXME_NOT_IMPLEMENTED(\"getDeviceUserId\"),\n getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),\n getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),\n hasPairing: async () => {\n logger.info(`[device] hasPairing`);\n const apdu = [0xe0, 0x51, 0x00, 0x00, 0xb5];\n const res = await run((transport) => transport.exchange(Buffer.from(apdu)));\n const hex = Buffer.from(res).toString(\"hex\");\n\n // 6f45 => this error means that there is no partition ID on the device\n // if no error, it means there is (at least) one\n //\n // 6a87 => TEMPORARY hack because Stax apparently does not implement\n // the \"get partition id\" APDU, so it returns \"incorrect length\"\n // easier to just assume that in this case there is no partition,\n // and try to insert one anyway (done on revault onboarding)\n //\n return hex !== \"6f45\" && hex !== \"6a87\";\n },\n\n initPairingHandshake: async (): Promise<{ pubKey: string; signature: string }> => {\n const res = await run((transport) => transport.send(0xe0, 0x46, 0x00, 0x00));\n const pubKeyLength = res.readInt8(0);\n const pubKey = res\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString(\"base64\");\n return { pubKey, signature };\n },\n\n openSession: FIXME_NOT_IMPLEMENTED(\"openSession\"),\n\n register: async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n invariant(applicationBuf.length === 32, \"application hex is expected to have 32 bytes\");\n\n const userNameBuff = Buffer.from(name);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([userNameBuff.length]),\n userNameBuff,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);\n\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x01, 0x00, 0x00], data),\n );\n\n let i = 0;\n const rfu = response.slice(i, (i += 1))[0]!;\n const pubKey = response.slice(i, (i += 65)).toString(\"hex\");\n const keyHandleLength = response.slice(i, ++i)[0]!;\n const keyHandle = response.slice(i, (i += keyHandleLength));\n return {\n u2fRegister: removeStatus(response),\n keyHandle,\n rfu,\n pubKey,\n };\n },\n registerData: async (params: { challenge: string }): Promise<string> => {\n const { challenge: strChallenge } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const response = await run((transport) => transport.send(0xe0, 0x03, 0x00, 0x00, challenge));\n return removeStatus(response).toString(\"hex\");\n },\n\n setPairing: async ({ pairing }) => {\n logger.info(`[device] setPairing`);\n const psdPayload = Buffer.from(pairing.blob, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(psdPayload.length, 0);\n const final = Buffer.concat([length, psdPayload]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x4e, 0x00, 0x00], final));\n },\n startKKPatternAsResponder: FIXME_NOT_IMPLEMENTED(\"startKKPatternAsResponder\"),\n startKPatternAsResponder: async (params) => {\n logger.info(`[device] startKPatternAsResponder`);\n const data = buildAttestation(params);\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x49, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n },\n validateVaultOperation: async (params) => {\n logger.info(`[device] validateVaultOperation`);\n const path = getPathFromPathString(PATHS.VALIDATION);\n const paths = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n let nextActionId = 1;\n let finalResponse;\n\n while (!finalResponse) {\n const screen = Buffer.from(params.actions[nextActionId - 1]!, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(screen.length, 0);\n const data = Buffer.concat([paths, length, screen]);\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x45, 0x00, 0x00], data),\n );\n const responseType = response.readInt8(0);\n let responseStatus = response.readUInt16BE(response.length - 2);\n if (responseType === STREAMING_NEXT_ACTION) {\n nextActionId = response.readUIntBE(1, 2);\n } else if (responseType === STREAMING_RESPONSE) {\n finalResponse = response.slice(3, response.length - 2);\n /* v8 ignore start */\n while (responseStatus !== 0x9000) {\n const resp = await run((transport) => transport.send(0x00, 0xc0, 0x00, 0x00));\n responseStatus = resp.readUInt16BE(resp.length - 2);\n finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);\n }\n } else {\n throw Error(`${responseType}`);\n }\n /* v8 ignore stop */\n }\n return finalResponse.toString(\"base64\");\n },\n\n sendAPDU: async (apduCommand: string) => {\n const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, \"hex\")));\n return Buffer.from(res).toString(\"hex\");\n },\n getVersion: async () => {\n const res = await run((transport) => transport.send(0xb0, 0x01, 0x00, 0x00));\n const appNameLen = res.readInt8(1);\n const appVersionLen = res.readInt8(2 + appNameLen);\n const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);\n\n const appVersion = Buffer.from(appVersionHex).toString();\n\n return appVersion;\n },\n poll,\n pollApp,\n };\n return device;\n}\n","import type { AppRouter } from \"@ledgerhq/revault-api\";\nimport { type TRPCClient, createTRPCClient, httpLink } from \"@trpc/client\";\nimport type { inferRouterInputs, inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nexport type TRPCClientOptions = {\n baseUrl: string;\n debugAuthToken?: string;\n rootAuthToken?: string;\n apiAccessToken?: string;\n psdAuth?: string;\n};\n\nexport type RevaultApiTRPCClient = TRPCClient<AppRouter>;\n\nexport type RouterInputs = inferRouterInputs<AppRouter>;\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n\nexport const createClient = (options: TRPCClientOptions): RevaultApiTRPCClient => {\n const trpc = createTRPCClient<AppRouter>({\n links: [\n httpLink({\n url: `${options.baseUrl}/trpc`,\n transformer: superjson,\n headers() {\n return {\n ...(options.debugAuthToken\n ? { \"x-revault-debug-auth-token\": options.debugAuthToken }\n : {}),\n ...(options.rootAuthToken\n ? { \"x-revault-root-auth-token\": options.rootAuthToken }\n : {}),\n ...(options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}),\n ...(options.apiAccessToken\n ? { Authorization: `Bearer ${options.apiAccessToken}` }\n : {}),\n };\n },\n }),\n ],\n });\n return trpc;\n};\n"]}
package/lib/engine.js CHANGED
@@ -339,12 +339,12 @@ function createRealDevice(options, logger) {
339
339
  }
340
340
 
341
341
  // src/trpc.ts
342
- import { createTRPCClient, httpBatchLink } from "@trpc/client";
342
+ import { createTRPCClient, httpLink } from "@trpc/client";
343
343
  import superjson from "superjson";
344
344
  var createClient = (options) => {
345
345
  const trpc = createTRPCClient({
346
346
  links: [
347
- httpBatchLink({
347
+ httpLink({
348
348
  url: `${options.baseUrl}/trpc`,
349
349
  transformer: superjson,
350
350
  headers() {