UNPKG

@blooo/hw-app-concordium

Version:

Ledger Hardware Wallet Concordium Application API

627 lines 30.4 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { StatusCodes } from "@ledgerhq/errors"; import { pathToBuffer, serializeConfigureDelegation, serializeSimpleTransfer, serializeSimpleTransferWithMemo, serializeTransferWithSchedule, serializeConfigureBaker, serializeTransferWithScheduleAndMemo, serializeRegisterData, serializeTransferToPublic, serializeDeployModule, serializeInitContract, serializeUpdateContract, serializeTransactionPayloads, serializeUpdateCredentials, serializeCredentialDeployment, serializePublicInfoForIp } from "./serialization"; import { encodeInt32, encodeInt8, encodeWord64 } from "./utils"; import { Mode } from "./type"; const PRIVATE_KEY_LENGTH = 32; const LEDGER_CLA = 0xe0; const NONE = 0x00; // FOR VERIFY ADRESS const P1_LEGACY_VERIFY_ADDRESS = 0x00; const P1_VERIFY_ADDRESS = 0x01; // FOR GET PUBLIC KEY const P1_NON_CONFIRM = 0x00; const P1_CONFIRM = 0x01; const P2_SIGNED_KEY = 0x01; // FOR SIGN TRANSACTION const P1_FIRST_BATCH = 0x01; const P1_AGGREGATION_KEY = 0x02; const P1_URL_LENGTH = 0x03; const P1_URL = 0x04; const P1_COMMISSION_FEE = 0x05; const P1_SUSPENDED = 0x06; const P1_FIRST_CHUNK = 0x00; const P1_INITIAL_WITH_MEMO = 0x01; const P1_INITIAL_WITH_MEMO_SCHEDULE = 0x02; const P1_MEMO_SCHEDULE = 0x03; const P1_REMAINING_AMOUNT = 0x01; const P1_DATA = 0x01; const P1_PROOF = 0x02; const P1_MEMO = 0x02; const P1_AMOUNT = 0x03; const P2_MORE = 0x80; const P2_LAST = 0x00; const P1_INITIAL_PACKET = 0x00; const P1_SCHEDULED_TRANSFER_PAIRS = 0x01; // Deploy Module const P1_SOURCE = 0x01; const P1_NAME = 0x01; const P1_PARAM = 0x02; // Update Credentials const P2_CREDENTIAL_INITIAL = 0x00; const P2_CREDENTIAL_CREDENTIAL_INDEX = 0x01; const P2_CREDENTIAL_CREDENTIAL = 0x02; const P2_CREDENTIAL_ID_COUNT = 0x03; const P2_CREDENTIAL_ID = 0x04; const P2_THRESHOLD = 0x05; //Deploy Credential const P1_VERIFICATION_KEY_LENGTH = 0x0A; const P1_VERIFICATION_KEY = 0x01; const P1_SIGNATURE_THRESHOLD = 0x02; const P1_AR_IDENTITY = 0x03; const P1_CREDENTIAL_DATES = 0x04; const P1_ATTRIBUTE_TAG = 0x05; const P1_ATTRIBUTE_VALUE = 0x06; const P1_LENGTH_OF_PROOFS = 0x07; const P1_PROOFS = 0x08; const P1_NEW_OR_EXISTING = 0x09; const INS = { VERIFY_ADDRESS: 0x00, GET_PUBLIC_KEY: 0x01, SIGN_TRANSFER: 0x02, SIGN_TRANSFER_SCHEDULE: 0x03, SIGN_CREDENTIAL_DEPLOYMENT: 0x04, EXPORT_PRIVATE_KEY_LEGACY: 0x05, SIGN_DEPLOY_MODULE: 0x06, SIGN_INIT_CONTRACT: 0x07, SIGN_UPDATE_CONTRACT: 0x08, SIGN_TRANSFER_TO_PUBLIC: 0x12, SIGN_CONFIGURE_DELEGATION: 0x17, SIGN_CONFIGURE_BAKER: 0x18, SIGN_PUBLIC_INFO_FOR_IP: 0x20, GET_APP_NAME: 0x21, SIGN_UPDATE_CREDENTIALS: 0x31, SIGN_TRANSFER_MEMO: 0x32, SIGN_TRANSFER_SCHEDULE_AND_MEMO: 0x34, SIGN_REGISTER_DATA: 0x35, EXPORT_PRIVATE_KEY_NEW: 0x37, }; /** * Concordium API * * @param transport a transport for sending commands to a device * @param scrambleKey a scramble key * * @example * import Concordium from "@blooo/hw-app-concordium"; * const Concordium = new Concordium(transport); */ export default class Concordium { constructor(transport, scrambleKey = "concordium_default_scramble_key") { this.transport = transport; this.transport.decorateAppAPIMethods(this, [ "getAddress", "verifyAddress", "verifyAddressLegacy", "getPublicKey", "exportPrivateKey", "signTransfer", "signTransferWithMemo", "signTransferWithSchedule", "signTransferWithScheduleAndMemo", "signConfigureDelegation", "signConfigureBaker", "signRegisterData", "signTransferToPublic", "signDeployModule", "signInitContract", "signUpdateContract", "signPublicInfoForIp", "signUpdateCredentials", "signCredentialDeployment", ], scrambleKey); } /** * Verify address. * * @param isLegacy - Flag to indicate if the legacy mode is used. * @param id - The identity number. * @param cred - The credential number. * @param idp - Mandatory if isLegacy is false. The identity provider number. * @returns A promise that resolves to an object containing the status. * * @example * concordium.verifyAddress(12,12,12).then(r => r.status) */ verifyAddress(isLegacy, id, cred, idp) { return __awaiter(this, void 0, void 0, function* () { try { const idEncoded = encodeInt32(id); let payload = Buffer.from(idEncoded); if (!isLegacy) { const idpEncoded = encodeInt32(idp); payload = Buffer.concat([payload, idpEncoded]); } const credEncoded = encodeInt32(cred); payload = Buffer.concat([payload, credEncoded]); yield this.sendToDevice(INS.VERIFY_ADDRESS, isLegacy ? P1_LEGACY_VERIFY_ADDRESS : P1_VERIFY_ADDRESS, NONE, payload); return { status: "success" }; } catch (error) { return { status: "failed" }; } ; }); } /** * Get Concordium address (public key) for a BIP32 path. * * @param path - A BIP32 path. * @param display - Flag to show display. * @param signedKey - Flag to sign key. * @returns A promise that resolves to an object with the public key and optionally the signed public key. * * @example * concordium.getPublicKey("1105'/0'/0'/0/0/0/0/", true, false) */ getPublicKey(path, display, signedKey) { return __awaiter(this, void 0, void 0, function* () { const pathBuffer = pathToBuffer(path); const publicKeyBuffer = yield this.sendToDevice(INS.GET_PUBLIC_KEY, display ? P1_NON_CONFIRM : P1_CONFIRM, signedKey ? P2_SIGNED_KEY : NONE, pathBuffer); const publicKeyLength = publicKeyBuffer[0]; if (signedKey) { return { publicKey: publicKeyBuffer.subarray(1, 1 + publicKeyLength).toString("hex"), signedPublicKey: publicKeyBuffer.subarray(1 + publicKeyLength).toString("hex"), }; } return { publicKey: publicKeyBuffer.subarray(1, 1 + publicKeyLength).toString("hex"), }; }); } /** * Export a private key. * * @param data - The data required for exporting the private key. * @param exportType - The type of export, either PRF_KEY_SEED or PRF_KEY. * @param mode - The mode, either DISPLAY, NO_DISPLAY, or EXPORT_CRED_ID. * @returns A promise that resolves to an object with the private key and optionally the credential ID. */ exportPrivateKeyLegacy(data, exportType, mode) { return __awaiter(this, void 0, void 0, function* () { const identityEncoded = encodeInt32(data.identity); const payload = Buffer.from(identityEncoded); const exportedPrivateKey = yield this.sendToDevice(INS.EXPORT_PRIVATE_KEY_LEGACY, mode, exportType, payload); if (mode === Mode.EXPORT_CRED_ID) { return { privateKey: exportedPrivateKey.subarray(0, PRIVATE_KEY_LENGTH).toString("hex"), credentialId: exportedPrivateKey.subarray(PRIVATE_KEY_LENGTH).toString("hex"), }; } return { privateKey: exportedPrivateKey.toString("hex"), }; }); } /** * Export a private key. * * @param data - The data required for exporting the private key. * @param exportType - The type of export, either PRF_KEY_SEED or PRF_KEY. * @param mode - The mode, either DISPLAY, NO_DISPLAY, or EXPORT_CRED_ID. * @returns A promise that resolves to an object with the private key and optionally the credential ID. */ exportPrivateKeyNew(data, exportType, mode) { return __awaiter(this, void 0, void 0, function* () { const identityEncoded = encodeInt32(data.identity); const identityProviderEncoded = encodeInt32(data.identityProvider); const payload = Buffer.concat([identityEncoded, identityProviderEncoded]); const exportedPrivateKey = yield this.sendToDevice(INS.EXPORT_PRIVATE_KEY_NEW, mode, exportType, payload); if (mode === Mode.EXPORT_CRED_ID) { return { privateKey: exportedPrivateKey.subarray(0, PRIVATE_KEY_LENGTH).toString("hex"), credentialId: exportedPrivateKey.subarray(PRIVATE_KEY_LENGTH).toString("hex"), }; } return { privateKey: exportedPrivateKey.toString("hex"), }; }); } /** * Signs a Concordium transaction using the specified account index. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. * @throws Error if the user declines the transaction. * * @example * concordium.signTransfer(txn).then(r => r.signature) */ signTransfer(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloads } = serializeSimpleTransfer(txn, path); let response; for (let i = 0; i < payloads.length; i++) { const lastChunk = i === payloads.length - 1; response = yield this.sendToDevice(INS.SIGN_TRANSFER, P1_FIRST_CHUNK + i, lastChunk ? P2_LAST : P2_MORE, payloads[i]); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a simple transfer with a memo. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signTransferWithMemo(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeaderAddressMemoLength, payloadsMemo, payloadsAmount } = serializeSimpleTransferWithMemo(txn, path); let response; yield this.sendToDevice(INS.SIGN_TRANSFER_MEMO, P1_INITIAL_WITH_MEMO, NONE, payloadHeaderAddressMemoLength[0]); yield this.sendToDevice(INS.SIGN_TRANSFER_MEMO, P1_MEMO, NONE, payloadsMemo[0]); response = yield this.sendToDevice(INS.SIGN_TRANSFER_MEMO, P1_AMOUNT, NONE, payloadsAmount[0]); if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a transfer with a schedule. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signTransferWithSchedule(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeaderAddressScheduleLength, payloadsSchedule } = serializeTransferWithSchedule(txn, path); let response; yield this.sendToDevice(INS.SIGN_TRANSFER_SCHEDULE, P1_INITIAL_PACKET, NONE, payloadHeaderAddressScheduleLength[0]); for (const schedule of payloadsSchedule) { response = yield this.sendToDevice(INS.SIGN_TRANSFER_SCHEDULE, P1_SCHEDULED_TRANSFER_PAIRS, NONE, schedule); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a transfer with a schedule and a memo. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signTransferWithScheduleAndMemo(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeaderAddressScheduleLengthAndMemoLength, payloadMemo, payloadsSchedule } = serializeTransferWithScheduleAndMemo(txn, path); let response; yield this.sendToDevice(INS.SIGN_TRANSFER_SCHEDULE_AND_MEMO, P1_INITIAL_WITH_MEMO_SCHEDULE, NONE, payloadHeaderAddressScheduleLengthAndMemoLength[0]); yield this.sendToDevice(INS.SIGN_TRANSFER_SCHEDULE_AND_MEMO, P1_MEMO_SCHEDULE, NONE, payloadMemo[0]); for (const schedule of payloadsSchedule) { response = yield this.sendToDevice(INS.SIGN_TRANSFER_SCHEDULE_AND_MEMO, P1_SCHEDULED_TRANSFER_PAIRS, NONE, schedule); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a configure delegation transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signConfigureDelegation(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloads } = serializeConfigureDelegation(txn, path); let response; for (let i = 0; i < payloads.length; i++) { const lastChunk = i === payloads.length - 1; response = yield this.sendToDevice(INS.SIGN_CONFIGURE_DELEGATION, P1_FIRST_CHUNK + i, lastChunk ? P2_LAST : P2_MORE, payloads[i]); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a configure baker transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signConfigureBaker(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeaderKindAndBitmap, payloadFirstBatch, payloadAggregationKeys, payloadUrlLength, payloadURL, payloadCommissionFee, payloadSuspended } = serializeConfigureBaker(txn, path); let response; yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_INITIAL_PACKET, NONE, payloadHeaderKindAndBitmap); yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_FIRST_BATCH, NONE, payloadFirstBatch); yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_AGGREGATION_KEY, NONE, payloadAggregationKeys); yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_URL_LENGTH, NONE, payloadUrlLength); yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_URL, NONE, payloadURL); yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_COMMISSION_FEE, NONE, payloadCommissionFee); response = yield this.sendToDevice(INS.SIGN_CONFIGURE_BAKER, P1_SUSPENDED, NONE, payloadSuspended); if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a register data transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signRegisterData(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeader, payloadsData } = serializeRegisterData(txn, path); let response; yield this.sendToDevice(INS.SIGN_REGISTER_DATA, P1_INITIAL_PACKET, NONE, payloadHeader[0]); for (const data of payloadsData) { response = yield this.sendToDevice(INS.SIGN_REGISTER_DATA, P1_DATA, NONE, data); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a transfer to public transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signTransferToPublic(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeader, payloadsAmountRecipientAndProofsLength, payloadsProofs } = serializeTransferToPublic(txn, path); let response; yield this.sendToDevice(INS.SIGN_TRANSFER_TO_PUBLIC, P1_INITIAL_PACKET, NONE, payloadHeader[0]); yield this.sendToDevice(INS.SIGN_TRANSFER_TO_PUBLIC, P1_REMAINING_AMOUNT, NONE, payloadsAmountRecipientAndProofsLength[0]); for (const proof of payloadsProofs) { response = yield this.sendToDevice(INS.SIGN_TRANSFER_TO_PUBLIC, P1_PROOF, NONE, proof); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a deploy module transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signDeployModule(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadsHeaderAndVersion, payloadSource } = serializeDeployModule(txn, path); let response; yield this.sendToDevice(INS.SIGN_DEPLOY_MODULE, P1_INITIAL_PACKET, P2_LAST, payloadsHeaderAndVersion[0]); response = yield this.sendToDevice(INS.SIGN_DEPLOY_MODULE, P1_SOURCE, P2_LAST, payloadSource); if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs an init contract transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signInitContract(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadsHeaderAndData, payloadsName, payloadsParam } = serializeInitContract(txn, path); let response; yield this.sendToDevice(INS.SIGN_INIT_CONTRACT, P1_INITIAL_PACKET, NONE, payloadsHeaderAndData[0]); for (const nameChunk of payloadsName) { yield this.sendToDevice(INS.SIGN_INIT_CONTRACT, P1_NAME, NONE, nameChunk); } for (const paramChunk of payloadsParam) { response = yield this.sendToDevice(INS.SIGN_INIT_CONTRACT, P1_PARAM, NONE, paramChunk); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs an update contract transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signUpdateContract(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadsHeaderAndData, payloadsName, payloadsParam } = serializeUpdateContract(txn, path); let response; yield this.sendToDevice(INS.SIGN_UPDATE_CONTRACT, P1_INITIAL_PACKET, NONE, payloadsHeaderAndData[0]); for (const nameChunk of payloadsName) { yield this.sendToDevice(INS.SIGN_UPDATE_CONTRACT, P1_NAME, NONE, nameChunk); } for (const paramChunk of payloadsParam) { response = yield this.sendToDevice(INS.SIGN_UPDATE_CONTRACT, P1_PARAM, NONE, paramChunk); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs public info for IP transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signPublicInfoForIp(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadIdCredPubAndRegIdAndKeysLenght, payloadKeys, payloadThreshold } = serializePublicInfoForIp(txn, path); let response; yield this.sendToDevice(INS.SIGN_PUBLIC_INFO_FOR_IP, P1_INITIAL_PACKET, NONE, payloadIdCredPubAndRegIdAndKeysLenght); for (const key of payloadKeys) { yield this.sendToDevice(INS.SIGN_PUBLIC_INFO_FOR_IP, P1_VERIFICATION_KEY, NONE, key); } response = yield this.sendToDevice(INS.SIGN_PUBLIC_INFO_FOR_IP, P1_SIGNATURE_THRESHOLD, NONE, payloadThreshold); if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs a credential deployment transaction. * * @param txn - The transaction to sign. * @param isNew - Flag indicating if it's a new credential. * @param addressOrExpiry - The address or expiry date. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signCredentialDeployment(txn, isNew, addressOrExpiry, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadDerivationPath, numberOfVerificationKeys, keyIndexAndSchemeAndVerificationKey, thresholdAndRegIdAndIPIdentity, encIdCredPubShareAndKey, validToAndCreatedAtAndAttributesLength, tag, valueLength, value, proofLength, proofs } = serializeCredentialDeployment(txn, path); let response; yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_INITIAL_PACKET, NONE, payloadDerivationPath); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_VERIFICATION_KEY_LENGTH, NONE, numberOfVerificationKeys); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_VERIFICATION_KEY, NONE, keyIndexAndSchemeAndVerificationKey); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_SIGNATURE_THRESHOLD, NONE, thresholdAndRegIdAndIPIdentity); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_AR_IDENTITY, NONE, encIdCredPubShareAndKey); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_CREDENTIAL_DATES, NONE, validToAndCreatedAtAndAttributesLength); for (let i = 0; i < Object.keys(txn.policy.revealedAttributes).length; i++) { const tagAndValueLength = Buffer.concat([tag[i], valueLength[i]]); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_ATTRIBUTE_TAG, NONE, tagAndValueLength); yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_ATTRIBUTE_VALUE, NONE, value[i]); } yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_LENGTH_OF_PROOFS, NONE, proofLength); const proofPayload = serializeTransactionPayloads(proofs); for (const proof of proofPayload) { yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_PROOFS, NONE, proof); } if (isNew) { const isNew = encodeInt8(0); const serializeExpiry = encodeWord64(addressOrExpiry); const expiry = Buffer.concat([isNew, serializeExpiry]); response = yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_NEW_OR_EXISTING, NONE, expiry); } else { const isNew = encodeInt8(1); const address = Buffer.concat([isNew, Buffer.from(addressOrExpiry, "hex")]); response = yield this.sendToDevice(INS.SIGN_CREDENTIAL_DEPLOYMENT, P1_NEW_OR_EXISTING, NONE, address); } if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Signs an update credentials transaction. * * @param txn - The transaction to sign. * @param path - The derivation path to use for signing. * @returns A promise that resolves to an object containing the signature. */ signUpdateCredentials(txn, path) { return __awaiter(this, void 0, void 0, function* () { const { payloadHeaderKindAndIndexLength, credentialIndex, numberOfVerificationKeys, keyIndexAndSchemeAndVerificationKey, thresholdAndRegIdAndIPIdentity, encIdCredPubShareAndKey, validToAndCreatedAtAndAttributesLength, tag, valueLength, value, proofLength, proofs, credentialIdCount, credentialIds, threshold } = serializeUpdateCredentials(txn, path); let response; yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, NONE, P2_CREDENTIAL_INITIAL, payloadHeaderKindAndIndexLength[0]); for (let i = 0; i < txn.payload.newCredentials.length; i++) { yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, NONE, P2_CREDENTIAL_CREDENTIAL_INDEX, credentialIndex[i]); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_VERIFICATION_KEY_LENGTH, P2_CREDENTIAL_CREDENTIAL, numberOfVerificationKeys[i]); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_VERIFICATION_KEY, P2_CREDENTIAL_CREDENTIAL, keyIndexAndSchemeAndVerificationKey[i]); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_SIGNATURE_THRESHOLD, P2_CREDENTIAL_CREDENTIAL, thresholdAndRegIdAndIPIdentity[i]); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_AR_IDENTITY, P2_CREDENTIAL_CREDENTIAL, encIdCredPubShareAndKey[i]); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_CREDENTIAL_DATES, P2_CREDENTIAL_CREDENTIAL, validToAndCreatedAtAndAttributesLength[i]); for (let j = 0; j < Object.keys(txn.payload.newCredentials[i].cdi.policy.revealedAttributes).length; j++) { const tagAndValueLength = Buffer.concat([tag[i][j], valueLength[i][j]]); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_ATTRIBUTE_TAG, P2_CREDENTIAL_CREDENTIAL, tagAndValueLength); yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_ATTRIBUTE_VALUE, P2_CREDENTIAL_CREDENTIAL, value[i][j]); } yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_LENGTH_OF_PROOFS, P2_CREDENTIAL_CREDENTIAL, proofLength[i]); const proofPayload = serializeTransactionPayloads(proofs[i]); for (const proof of proofPayload) { yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, P1_PROOFS, P2_CREDENTIAL_CREDENTIAL, proof); } } yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, NONE, P2_CREDENTIAL_ID_COUNT, credentialIdCount); for (let i = 0; i < txn.payload.removeCredentialIds.length; i++) { yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, NONE, P2_CREDENTIAL_ID, credentialIds[i]); } response = yield this.sendToDevice(INS.SIGN_UPDATE_CREDENTIALS, NONE, P2_THRESHOLD, threshold); if (response.length === 1) throw new Error("User has declined."); return { signature: response.toString("hex"), }; }); } /** * Sends a command to the device. * * @param instruction - The instruction code. * @param p1 - The first parameter. * @param p2 - The second parameter. * @param payload - The payload to send. * @returns A promise that resolves to the device's response. */ sendToDevice(instruction_1, p1_1) { return __awaiter(this, arguments, void 0, function* (instruction, p1, p2 = 0x00, payload) { const acceptStatusList = [StatusCodes.OK]; const reply = yield this.transport.send(LEDGER_CLA, instruction, p1, p2, payload, acceptStatusList); this.throwOnFailure(reply); return reply.subarray(0, reply.length - 2); }); } /** * Throws an error if the device response indicates a failure. * * @param reply - The device's response. */ throwOnFailure(reply) { // transport makes sure reply has a valid length const status = reply.readUInt16BE(reply.length - 2); switch (status) { default: return; } } } //# sourceMappingURL=Concordium.js.map