From 971243c14ed5ae469a3fae6407af978089fa6a32 Mon Sep 17 00:00:00 2001 From: Ravi Hegde Date: Tue, 23 Jun 2026 16:27:49 +0530 Subject: [PATCH] feat(sdk-coin-canton): add allocation reject builder Ticket: CHALO-691 --- .../src/lib/allocationRejectBuilder.ts | 115 +++++++++++++++ modules/sdk-coin-canton/src/lib/index.ts | 1 + .../src/lib/transactionBuilderFactory.ts | 8 ++ modules/sdk-coin-canton/src/lib/utils.ts | 37 +++++ modules/sdk-coin-canton/test/resources.ts | 21 +++ .../allocationRejectBuilder.ts | 133 ++++++++++++++++++ .../sdk-core/src/account-lib/baseCoin/enum.ts | 2 + 7 files changed, 317 insertions(+) create mode 100644 modules/sdk-coin-canton/src/lib/allocationRejectBuilder.ts create mode 100644 modules/sdk-coin-canton/test/unit/builder/allocationReject/allocationRejectBuilder.ts diff --git a/modules/sdk-coin-canton/src/lib/allocationRejectBuilder.ts b/modules/sdk-coin-canton/src/lib/allocationRejectBuilder.ts new file mode 100644 index 0000000000..d1feb91979 --- /dev/null +++ b/modules/sdk-coin-canton/src/lib/allocationRejectBuilder.ts @@ -0,0 +1,115 @@ +import { InvalidTransactionError, PublicKey, TransactionType } from '@bitgo/sdk-core'; +import { BaseCoin as CoinConfig } from '@bitgo/statics'; +import { CantonPrepareCommandResponse, CantonTransferAcceptRejectRequest } from './iface'; +import { TransactionBuilder } from './transactionBuilder'; +import { Transaction } from './transaction/transaction'; +import utils from './utils'; + +export class AllocationRejectBuilder extends TransactionBuilder { + private _commandId: string; + private _contractId: string; + private _actAsPartyId: string; + + constructor(_coinConfig: Readonly) { + super(_coinConfig); + } + + initBuilder(tx: Transaction): void { + super.initBuilder(tx); + this.setTransactionType(); + } + + get transactionType(): TransactionType { + return TransactionType.AllocationReject; + } + + setTransactionType(): void { + this.transaction.transactionType = TransactionType.AllocationReject; + } + + setTransaction(transaction: CantonPrepareCommandResponse): void { + this.transaction.prepareCommand = transaction; + } + + /** @inheritDoc */ + addSignature(publicKey: PublicKey, signature: Buffer): void { + if (!this.transaction) { + throw new InvalidTransactionError('transaction is empty!'); + } + this._signatures.push({ publicKey, signature }); + const pubKeyBase64 = utils.getBase64FromHex(publicKey.pub); + this.transaction.signerFingerprint = utils.getAddressFromPublicKey(pubKeyBase64); + this.transaction.signatures = signature.toString('base64'); + } + + /** + * Sets the unique id for the allocation rejection + * Also sets the _id of the transaction + * + * @param id - A uuid + * @returns The current builder instance for chaining. + * @throws Error if id is empty. + */ + commandId(id: string): this { + if (!id || !id.trim()) { + throw new Error('commandId must be a non-empty string'); + } + this._commandId = id.trim(); + this.transaction.id = id.trim(); + return this; + } + + /** + * Sets the allocation rejection contract id + * + * @param id - canton allocation rejection contract id + * @returns The current builder instance for chaining. + * @throws Error if id is empty. + */ + contractId(id: string): this { + if (!id || !id.trim()) { + throw new Error('contractId must be a non-empty string'); + } + this._contractId = id.trim(); + return this; + } + + /** + * Sets the party acting as the rejector + * + * @param id - the party id (address) + * @returns The current builder instance for chaining. + * @throws Error if id is empty. + */ + actAs(id: string): this { + if (!id || !id.trim()) { + throw new Error('actAsPartyId must be a non-empty string'); + } + this._actAsPartyId = id.trim(); + return this; + } + + /** + * Builds and returns the CantonTransferAcceptRejectRequest object from the builder's internal state. + * + * @returns {CantonTransferAcceptRejectRequest} - A fully constructed and validated request object for allocation rejection. + * @throws {Error} If any required field is missing or fails validation. + */ + toRequestObject(): CantonTransferAcceptRejectRequest { + this.validate(); + + return { + commandId: this._commandId, + contractId: this._contractId, + verboseHashing: false, + actAs: [this._actAsPartyId], + readAs: [], + }; + } + + private validate(): void { + if (!this._commandId) throw new Error('commandId is missing'); + if (!this._contractId) throw new Error('contractId is missing'); + if (!this._actAsPartyId) throw new Error('actAs partyId is missing'); + } +} diff --git a/modules/sdk-coin-canton/src/lib/index.ts b/modules/sdk-coin-canton/src/lib/index.ts index 2c0bffae5c..bc5994865d 100644 --- a/modules/sdk-coin-canton/src/lib/index.ts +++ b/modules/sdk-coin-canton/src/lib/index.ts @@ -4,6 +4,7 @@ import * as Interface from './iface'; export { CantonCommandBuilder } from './cantonCommandBuilder'; export { AllocationAllocateBuilder } from './allocationAllocateBuilder'; export { AllocationAllocateWithdrawnBuilder } from './allocationAllocateWithdrawnBuilder'; +export { AllocationRejectBuilder } from './allocationRejectBuilder'; export { AllocationRequestBuilder } from './allocationRequestBuilder'; export { CosignDelegationAcceptBuilder } from './cosignDelegationAcceptBuilder'; export { CosignDelegationProposalBuilder } from './cosignDelegationProposalBuilder'; diff --git a/modules/sdk-coin-canton/src/lib/transactionBuilderFactory.ts b/modules/sdk-coin-canton/src/lib/transactionBuilderFactory.ts index 47cbbebcd4..6dc2eb4b8d 100644 --- a/modules/sdk-coin-canton/src/lib/transactionBuilderFactory.ts +++ b/modules/sdk-coin-canton/src/lib/transactionBuilderFactory.ts @@ -7,6 +7,7 @@ import { import { BaseCoin as CoinConfig } from '@bitgo/statics'; import { AllocationAllocateBuilder } from './allocationAllocateBuilder'; import { AllocationAllocateWithdrawnBuilder } from './allocationAllocateWithdrawnBuilder'; +import { AllocationRejectBuilder } from './allocationRejectBuilder'; import { AllocationRequestBuilder } from './allocationRequestBuilder'; import { CantonCommandBuilder } from './cantonCommandBuilder'; import { CosignDelegationAcceptBuilder } from './cosignDelegationAcceptBuilder'; @@ -69,6 +70,9 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory { case TransactionType.AllocationRequest: { return this.getAllocationRequestBuilder(tx); } + case TransactionType.AllocationReject: { + return this.getAllocationRejectBuilder(tx); + } case TransactionType.CantonCommand: { return this.getCantonCommandBuilder(tx); } @@ -87,6 +91,10 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory { return TransactionBuilderFactory.initializeBuilder(tx, new AllocationAllocateWithdrawnBuilder(this._coinConfig)); } + getAllocationRejectBuilder(tx?: Transaction): AllocationRejectBuilder { + return TransactionBuilderFactory.initializeBuilder(tx, new AllocationRejectBuilder(this._coinConfig)); + } + getAllocationRequestBuilder(tx?: Transaction): AllocationRequestBuilder { return TransactionBuilderFactory.initializeBuilder(tx, new AllocationRequestBuilder(this._coinConfig)); } diff --git a/modules/sdk-coin-canton/src/lib/utils.ts b/modules/sdk-coin-canton/src/lib/utils.ts index ed5dec3000..970c630887 100644 --- a/modules/sdk-coin-canton/src/lib/utils.ts +++ b/modules/sdk-coin-canton/src/lib/utils.ts @@ -375,6 +375,43 @@ export class Utils implements BaseUtils { break; } + case TransactionType.AllocationReject: { + // RejectedDvp create node → dvp.{seller=sender, buyer=receiver, terms.deliveries[0].{amount, instrument.{admin, id}}} + const rejectedDvpFields = findCreateNodeFields('RejectedDvp'); + if (rejectedDvpFields) { + const dvpField = getField(rejectedDvpFields, 'dvp'); + if (dvpField?.oneofKind === 'record') { + const dvpFields = dvpField.record?.fields ?? []; + const sellerData = getField(dvpFields, 'seller'); + if (sellerData?.oneofKind === 'party') sender = sellerData.party ?? ''; + const buyerData = getField(dvpFields, 'buyer'); + if (buyerData?.oneofKind === 'party') receiver = buyerData.party ?? ''; + const termsField = getField(dvpFields, 'terms'); + if (termsField?.oneofKind === 'record') { + const termsFields = termsField.record?.fields ?? []; + const deliveriesField = getField(termsFields, 'deliveries'); + if (deliveriesField?.oneofKind === 'list') { + const firstDelivery = deliveriesField.list?.elements?.[0]?.sum; + if (firstDelivery?.oneofKind === 'record') { + const deliveryFields = firstDelivery.record?.fields ?? []; + const amountData = getField(deliveryFields, 'amount'); + if (amountData?.oneofKind === 'numeric') amount = amountData.numeric ?? ''; + const instrumentField = getField(deliveryFields, 'instrument'); + if (instrumentField?.oneofKind === 'record') { + const instrumentFields = instrumentField.record?.fields ?? []; + const adminData = getField(instrumentFields, 'admin'); + if (adminData?.oneofKind === 'party') instrumentAdmin = adminData.party ?? ''; + const idData = getField(instrumentFields, 'id'); + if (idData?.oneofKind === 'text') instrumentId = idData.text ?? ''; + } + } + } + } + } + } + break; + } + case TransactionType.CosignDelegationAccept: { // exercise CosigningDelegationProposal_Accept → actingParties[0] = signer (sender) const signerParty = findExerciseActingParty('CosigningDelegationProposal_Accept'); diff --git a/modules/sdk-coin-canton/test/resources.ts b/modules/sdk-coin-canton/test/resources.ts index d1774789a0..20c111f9d2 100644 --- a/modules/sdk-coin-canton/test/resources.ts +++ b/modules/sdk-coin-canton/test/resources.ts @@ -144,6 +144,13 @@ export const TransferRejection = { '006d2cdb952b4d550951a48617e44d9355314b0b90a0e20e8b3f3f4ad09fb020c4ca111220f623b223d99fe1fbc3fc3503e044f1de576d93b26fdf12f0e491031d72cf4765', }; +export const AllocationRejection = { + partyId: 'ravi-test-party-1::12205b4e3537a95126d90604592344d8ad3c3ddccda4f79901954280ee19c576714d', + commandId: '5f2a1b3c-7d8e-4f9a-b0c1-2d3e4f5a6b7c', + contractId: + '00f169e1d84c476cb1321eff8ac2aebc9ce1c6b20790db5e788ee4ca87256a0639ca1112205a8d0e780cf3b3115cf8be0d6315f4aed6a1c25b67e8c5d64cf9848d0458fd17', +}; + export const TransferAcknowledgeRequest = { contractId: '001b549bfa833bab661ab30e4d0a3ab0ec01fcc4a2bef5369795f4928147706353ca1112205a8d0e780cf3b3115cf8be0d6315f4aed6a1c25b67e8c5d64cf9848d0458fd17', @@ -312,6 +319,20 @@ export const CantonAllocationAllocatePrepareResponse = { }, }; +export const CantonAllocationRejectPrepareResponse = { + preparedTransaction: + 'CrwiCgMyLjESATAamBIKATHCPpESCo4SCgMyLjESQjAwOTg5NWJlYzA0MjI2ZjViN2I0MzI2ZDk4ZmNkYzM2MmM2MzdjMTM0OTk0ZmZjZTc0YzdmNTRjNjQxNzA1Y2JjMxoZdXRpbGl0eS1zZXR0bGVtZW50LWFwcC12MSJ0CkBmMTY5ZTFkODRjNDc2Y2IxMzIxZWZmOGFjMmFlYmM5Y2UxYzZiMjA3OTBkYjVlNzg4ZWU0Y2E4NzI1NmEwNjM5EiNVdGlsaXR5LlNldHRsZW1lbnQuQXBwLlYxLk1vZGVsLkR2cBoLUmVqZWN0ZWREdnAq3w1y3A0KdApAZjE2OWUxZDg0YzQ3NmNiMTMyMWVmZjhhYzJhZWJjOWNlMWM2YjIwNzkwZGI1ZTc4OGVlNGNhODcyNTZhMDYzORIjVXRpbGl0eS5TZXR0bGVtZW50LkFwcC5WMS5Nb2RlbC5EdnAaC1JlamVjdGVkRHZwEvELCgNkdnAS6Qty5gsKbApAZjE2OWUxZDg0YzQ3NmNiMTMyMWVmZjhhYzJhZWJjOWNlMWM2YjIwNzkwZGI1ZTc4OGVlNGNhODcyNTZhMDYzORIjVXRpbGl0eS5TZXR0bGVtZW50LkFwcC5WMS5Nb2RlbC5EdnAaA0R2cBJiCghvcGVyYXRvchJWOlRyYXZpLW5ldy1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDISVgoFYnV5ZXISTTpLMTIyMDg6OjEyMjA4MzA4MmU5YWYxNTZmZWFlYjdhZmQzNjNhMGVlNWZmYTFmZDE2MDk0N2I2NDdhMTM5YTdlMGMyZWQ3OGY1ZGM3EmMKBnNlbGxlchJZOldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIS1AgKBXRlcm1zEsoIcscICm4KQGYxNjllMWQ4NGM0NzZjYjEzMjFlZmY4YWMyYWViYzljZTFjNmIyMDc5MGRiNWU3ODhlZTRjYTg3MjU2YTA2MzkSI1V0aWxpdHkuU2V0dGxlbWVudC5BcHAuVjEuTW9kZWwuRHZwGgVUZXJtcxIVCgJpZBIPQg1DQVNILTdGQUUwRjA5ErYDCgpkZWxpdmVyaWVzEqcDWqQDCqEDcp4DCncKQGYxNjllMWQ4NGM0NzZjYjEzMjFlZmY4YWMyYWViYzljZTFjNmIyMDc5MGRiNWU3ODhlZTRjYTg3MjU2YTA2MzkSH1V0aWxpdHkuU2V0dGxlbWVudC5BcHAuVjEuVHlwZXMaEkluc3RydW1lbnRRdWFudGl0eRKIAgoKaW5zdHJ1bWVudBL5AXL2AQpsCkA3MThhMGY3N2U1MDVhOGRlMjJmMTg4YmQ0Yzg3ZmU3NDEwMTI3NGU5ZDRjYjFiZmFjN2QwOWFlYzcxNThkMzViEhpTcGxpY2UuQXBpLlRva2VuLkhvbGRpbmdWMRoMSW5zdHJ1bWVudElkEnMKBWFkbWluEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EhEKAmlkEgtCCVRlc3RDb2luMRIYCgZhbW91bnQSDjIMMi4wMDAwMDAwMDAwErQDCghwYXltZW50cxKnA1qkAwqhA3KeAwp3CkBmMTY5ZTFkODRjNDc2Y2IxMzIxZWZmOGFjMmFlYmM5Y2UxYzZiMjA3OTBkYjVlNzg4ZWU0Y2E4NzI1NmEwNjM5Eh9VdGlsaXR5LlNldHRsZW1lbnQuQXBwLlYxLlR5cGVzGhJJbnN0cnVtZW50UXVhbnRpdHkSiAIKCmluc3RydW1lbnQS+QFy9gEKbApANzE4YTBmNzdlNTA1YThkZTIyZjE4OGJkNGM4N2ZlNzQxMDEyNzRlOWQ0Y2IxYmZhYzdkMDlhZWM3MTU4ZDM1YhIaU3BsaWNlLkFwaS5Ub2tlbi5Ib2xkaW5nVjEaDEluc3RydW1lbnRJZBJzCgVhZG1pbhJqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmORIRCgJpZBILQglUZXN0VG9rZW4SGAoGYW1vdW50Eg4yDDAuMTAwMDAwMDAwMBIWCgljcmVhdGVkQXQSCSlnM7a/5lQGABIbCg5hbGxvY2F0ZUJlZm9yZRIJKQiDbCrnVAYAEhkKDHNldHRsZUJlZm9yZRIJKQhVtpXnVAYAEgwKBnJlYXNvbhICQgASYgoFYWN0b3ISWTpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyMlRyYXZpLW5ldy1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDI6SzEyMjA4OjoxMjIwODMwODJlOWFmMTU2ZmVhZWI3YWZkMzYzYTBlZTVmZmExZmQxNjA5NDdiNjQ3YTEzOWE3ZTBjMmVkNzhmNWRjNzpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyOlRyYXZpLW5ldy1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIazA8KATDCPsUPGsIPCgMyLjESigEwMDIzYTE1NDMwMmQxOTZkOWNhZmJjZDgzMmU5NTgyNGY4MjJiNTk5OTRmYmQyZmFkMjU1YTZjZDhmMTFkMjYyNGRjYTEyMTIyMDYyMTFjODg2Y2U0Yzk2MmJlYjNlMWUzNzgyOTMyOTBlYTYyMTNjMzAwZmY3OGEwMjBmMzhhNGIzNDViNDEyNGYaGXV0aWxpdHktc2V0dGxlbWVudC1hcHAtdjEibApAZjE2OWUxZDg0YzQ3NmNiMTMyMWVmZjhhYzJhZWJjOWNlMWM2YjIwNzkwZGI1ZTc4OGVlNGNhODcyNTZhMDYzORIjVXRpbGl0eS5TZXR0bGVtZW50LkFwcC5WMS5Nb2RlbC5EdnAaA0R2cCpLMTIyMDg6OjEyMjA4MzA4MmU5YWYxNTZmZWFlYjdhZmQzNjNhMGVlNWZmYTFmZDE2MDk0N2I2NDdhMTM5YTdlMGMyZWQ3OGY1ZGM3KldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIqVHJhdmktbmV3LXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjJLMTIyMDg6OjEyMjA4MzA4MmU5YWYxNTZmZWFlYjdhZmQzNjNhMGVlNWZmYTFmZDE2MDk0N2I2NDdhMTM5YTdlMGMyZWQ3OGY1ZGM3MldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIyVHJhdmktbmV3LXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyQnsKQDZmZTg0ODUzMGIyNDA0MDE3YzRhMTI4NzRjOTU2YWQ3ZDVjOGE0MTllZTliMDQwZjk2YjVjMTMxNzJkMmUxOTMSJFNwbGljZS5BcGkuVG9rZW4uQWxsb2NhdGlvblJlcXVlc3RWMRoRQWxsb2NhdGlvblJlcXVlc3RKGEFsbG9jYXRpb25SZXF1ZXN0X1JlamVjdFKxBXKuBQqCAQpANmZlODQ4NTMwYjI0MDQwMTdjNGExMjg3NGM5NTZhZDdkNWM4YTQxOWVlOWIwNDBmOTZiNWMxMzE3MmQyZTE5MxIkU3BsaWNlLkFwaS5Ub2tlbi5BbGxvY2F0aW9uUmVxdWVzdFYxGhhBbGxvY2F0aW9uUmVxdWVzdF9SZWplY3QSYgoFYWN0b3ISWTpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyEsIDCglleHRyYUFyZ3MStANysQMKagpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGglFeHRyYUFyZ3MSjAEKB2NvbnRleHQSgAFyfgpuCkA0ZGVkNmI2NjhjYjNiNjRmN2E4OGEzMDg3NGNkNDFjNzU4MjlmNWUwNjRiM2ZiYmFkZjQxZWM3ZTgzNjMzNTRmEhtTcGxpY2UuQXBpLlRva2VuLk1ldGFkYXRhVjEaDUNob2ljZUNvbnRleHQSDAoGdmFsdWVzEgJiABKzAQoEbWV0YRKqAXKnAQppCkA0ZGVkNmI2NjhjYjNiNjRmN2E4OGEzMDg3NGNkNDFjNzU4MjlmNWUwNjRiM2ZiYmFkZjQxZWM3ZTgzNjMzNTRmEhtTcGxpY2UuQXBpLlRva2VuLk1ldGFkYXRhVjEaCE1ldGFkYXRhEjoKBnZhbHVlcxIwYi4KLAoNc3BsaWNlLnJlYXNvbhIbQhlTZWxsZXIgcmVqZWN0ZWQgdGhlIHRyYWRlWAFiATFqgwJygAIKeApANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGhdDaG9pY2VFeGVjdXRpb25NZXRhZGF0YRKDAQoEbWV0YRJ7cnkKaQpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGghNZXRhZGF0YRIMCgZ2YWx1ZXMSAmIAIiISIPNpOrhmP8hgiaV8MxIkDwZ/rf7nhyN3LLjZh7dWmA1yIiQIARIg0G40bjkoRq+ORVI+q3VNhgAZAR5AOEKACVXKZkB8a3cSxx0SfwpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyEiQwODkwOGY1YS01ZDMzLTQ5MDktYjU4NC1lZTRmNDEyNmM2ZWEaWWdsb2JhbC1kb21haW46OjEyMjBiZTU4YzI5ZTY1ZGU0MGJmMjczYmUxZGMyYjI2NmQ0M2E5YTAwMmVhNWIxODk1NWFlZWY3YWFjODgxYmI0NzFhOjozNS0zKiQ1ZDQxZDVjYS0xYWRjLTRhZWItYWRiNy1kMTVlODFjOWE2OWIwy+KV1eyclQM6uRsK/xEKAzIuMRKKATAwMjNhMTU0MzAyZDE5NmQ5Y2FmYmNkODMyZTk1ODI0ZjgyMmI1OTk5NGZiZDJmYWQyNTVhNmNkOGYxMWQyNjI0ZGNhMTIxMjIwNjIxMWM4ODZjZTRjOTYyYmViM2UxZTM3ODI5MzI5MGVhNjIxM2MzMDBmZjc4YTAyMGYzOGE0YjM0NWI0MTI0ZhoZdXRpbGl0eS1zZXR0bGVtZW50LWFwcC12MSJsCkAzNGFiODg2ZWU4OGIwNDU2MzdmZjQxNmY1NTg3MzQzMDlmNTY1MGZlYzgxYTYwM2NiNWRiNzZiYmQ4NjNiOTUwEiNVdGlsaXR5LlNldHRsZW1lbnQuQXBwLlYxLk1vZGVsLkR2cBoDRHZwKukLcuYLCmwKQGYxNjllMWQ4NGM0NzZjYjEzMjFlZmY4YWMyYWViYzljZTFjNmIyMDc5MGRiNWU3ODhlZTRjYTg3MjU2YTA2MzkSI1V0aWxpdHkuU2V0dGxlbWVudC5BcHAuVjEuTW9kZWwuRHZwGgNEdnASYgoIb3BlcmF0b3ISVjpUcmF2aS1uZXctcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyElYKBWJ1eWVyEk06SzEyMjA4OjoxMjIwODMwODJlOWFmMTU2ZmVhZWI3YWZkMzYzYTBlZTVmZmExZmQxNjA5NDdiNjQ3YTEzOWE3ZTBjMmVkNzhmNWRjNxJjCgZzZWxsZXISWTpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyEtQICgV0ZXJtcxLKCHLHCApuCkBmMTY5ZTFkODRjNDc2Y2IxMzIxZWZmOGFjMmFlYmM5Y2UxYzZiMjA3OTBkYjVlNzg4ZWU0Y2E4NzI1NmEwNjM5EiNVdGlsaXR5LlNldHRsZW1lbnQuQXBwLlYxLk1vZGVsLkR2cBoFVGVybXMSFQoCaWQSD0INQ0FTSC03RkFFMEYwORK2AwoKZGVsaXZlcmllcxKnA1qkAwqhA3KeAwp3CkBmMTY5ZTFkODRjNDc2Y2IxMzIxZWZmOGFjMmFlYmM5Y2UxYzZiMjA3OTBkYjVlNzg4ZWU0Y2E4NzI1NmEwNjM5Eh9VdGlsaXR5LlNldHRsZW1lbnQuQXBwLlYxLlR5cGVzGhJJbnN0cnVtZW50UXVhbnRpdHkSiAIKCmluc3RydW1lbnQS+QFy9gEKbApANzE4YTBmNzdlNTA1YThkZTIyZjE4OGJkNGM4N2ZlNzQxMDEyNzRlOWQ0Y2IxYmZhYzdkMDlhZWM3MTU4ZDM1YhIaU3BsaWNlLkFwaS5Ub2tlbi5Ib2xkaW5nVjEaDEluc3RydW1lbnRJZBJzCgVhZG1pbhJqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmORIRCgJpZBILQglUZXN0Q29pbjESGAoGYW1vdW50Eg4yDDIuMDAwMDAwMDAwMBK0AwoIcGF5bWVudHMSpwNapAMKoQNyngMKdwpAZjE2OWUxZDg0YzQ3NmNiMTMyMWVmZjhhYzJhZWJjOWNlMWM2YjIwNzkwZGI1ZTc4OGVlNGNhODcyNTZhMDYzORIfVXRpbGl0eS5TZXR0bGVtZW50LkFwcC5WMS5UeXBlcxoSSW5zdHJ1bWVudFF1YW50aXR5EogCCgppbnN0cnVtZW50EvkBcvYBCmwKQDcxOGEwZjc3ZTUwNWE4ZGUyMmYxODhiZDRjODdmZTc0MTAxMjc0ZTlkNGNiMWJmYWM3ZDA5YWVjNzE1OGQzNWISGlNwbGljZS5BcGkuVG9rZW4uSG9sZGluZ1YxGgxJbnN0cnVtZW50SWQScwoFYWRtaW4SajpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkSEQoCaWQSC0IJVGVzdFRva2VuEhgKBmFtb3VudBIOMgwwLjEwMDAwMDAwMDASFgoJY3JlYXRlZEF0EgkpZzO2v+ZUBgASGwoOYWxsb2NhdGVCZWZvcmUSCSkIg2wq51QGABIZCgxzZXR0bGVCZWZvcmUSCSkIVbaV51QGADJLMTIyMDg6OjEyMjA4MzA4MmU5YWYxNTZmZWFlYjdhZmQzNjNhMGVlNWZmYTFmZDE2MDk0N2I2NDdhMTM5YTdlMGMyZWQ3OGY1ZGM3MldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIyVHJhdmktbmV3LXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjpLMTIyMDg6OjEyMjA4MzA4MmU5YWYxNTZmZWFlYjdhZmQzNjNhMGVlNWZmYTFmZDE2MDk0N2I2NDdhMTM5YTdlMGMyZWQ3OGY1ZGM3OldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDI6VHJhdmktbmV3LXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMsA+5+bY/euclQPSPqkJCgMyLjESoQkKRQAjoVQwLRltnK+82DLpWCT4IrWZlPvS+tJVps2PEdJiTcoSEiBiEciGzkyWK+s+HjeCkykOpiE8MA/3igIPOKSzRbQSTxIZdXRpbGl0eS1zZXR0bGVtZW50LWFwcC12MRpxCkAzNGFiODg2ZWU4OGIwNDU2MzdmZjQxNmY1NTg3MzQzMDlmNTY1MGZlYzgxYTYwM2NiNWRiNzZiYmQ4NjNiOTUwEgdVdGlsaXR5EgpTZXR0bGVtZW50EgNBcHASAlYxEgVNb2RlbBIDRHZwGgNEdnAimAVqlQUKWApWOlRyYXZpLW5ldy1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIKTwpNOksxMjIwODo6MTIyMDgzMDgyZTlhZjE1NmZlYWViN2FmZDM2M2EwZWU1ZmZhMWZkMTYwOTQ3YjY0N2ExMzlhN2UwYzJlZDc4ZjVkYzcKWwpZOldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIKigMKhwNqhAMKEQoPQg1DQVNILTdGQUUwRjA5CqIBCp8BWpwBCpkBapYBCoEBCn9qfQpsCmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5Cg0KC0IJVGVzdENvaW4xChAKDjIMMi4wMDAwMDAwMDAwCqIBCp8BWpwBCpkBapYBCoEBCn9qfQpsCmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5Cg0KC0IJVGVzdFRva2VuChAKDjIMMC4xMDAwMDAwMDAwCgsKCSlnM7a/5lQGAAoLCgkpCINsKudUBgAKCwoJKQhVtpXnVAYAKksxMjIwODo6MTIyMDgzMDgyZTlhZjE1NmZlYWViN2FmZDM2M2EwZWU1ZmZhMWZkMTYwOTQ3YjY0N2ExMzlhN2UwYzJlZDc4ZjVkYzcqV3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMipUcmF2aS1uZXctcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyOWcztr/mVAYAQioKJgokCAESIOsFSnyovaSZS+63gvHVG7bl8C6R5ZJK12B+6U8OkEjJEB4=', + preparedTransactionHash: 'L1KfrA5exnpsOqtXODGj2gNF+y/dv/onPtVvGJ5km7c=', + hashingSchemeVersion: 'HASHING_SCHEME_VERSION_V2', + hashingDetails: null, + costEstimation: { + estimationTimestamp: '2026-06-23T07:34:27.657227Z', + confirmationRequestTrafficCostEstimation: 4114, + confirmationResponseTrafficCostEstimation: 0, + totalTrafficCostEstimation: 4114, + }, +}; + export const CantonAllocationWithdrawPrepareResponse = { preparedTransaction: 'CsgmCgMyLjESATAalAwKATLCPo0MCooMCgMyLjESQjAwOWQwNzhmNTZjYzUzMWMzMmFmNzU3OTlkMzViMmFjYzVlM2U2NWExZjhkNTdjZmMwY2E2ZDJkNGY0MDQwMTA0YxobdXRpbGl0eS1yZWdpc3RyeS1ob2xkaW5nLXYwInAKQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGgdIb2xkaW5nKqkHcqYHCnAKQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGgdIb2xkaW5nEnYKCG9wZXJhdG9yEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EnYKCHByb3ZpZGVyEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EncKCXJlZ2lzdHJhchJqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmORJiCgVvd25lchJZOldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDISvQIKCmluc3RydW1lbnQSrgJyqwIKewpAODEwNzg5OWFjNDcyM2NlOTg2YmY3ZDI3NDE2NTM0ZTU3NmU1NGI5MjE2MWU0NjE1MGE1OTVmYjc4ZmYzZDNhMRIhVXRpbGl0eS5SZWdpc3RyeS5Ib2xkaW5nLlYwLlR5cGVzGhRJbnN0cnVtZW50SWRlbnRpZmllchJ0CgZzb3VyY2USajpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkSEQoCaWQSC0IJVGVzdFRva2VuEiMKBnNjaGVtZRIZQhdSZWdpc3RyYXJJbnRlcm5hbFNjaGVtZRILCgVsYWJlbBICQgASGAoGYW1vdW50Eg4yDDUuMDAwMDAwMDAwMDJoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkyV3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4Zjk6V3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMhrKCgoBMcI+wwoawAoKAzIuMRKKATAwNzc4NjljNjUzNjg0ZjdmYjQzZjJhYjc5MmQzZmRhMTViYTZjZDMxZTVhYzdkNWZlMDMyYTdjNzg4MzQ0Y2QxNWNhMTIxMjIwYTk0MmU1YzczNDI5YmZkNjRmMzExMWQ3NjcxODllN2RjNjNhOWI5ZDFhN2UyODhlMzkxYzMwYzhkMGNkYmZjMxobdXRpbGl0eS1yZWdpc3RyeS1ob2xkaW5nLXYwInAKQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGgdIb2xkaW5nKmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOSpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyMmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOTJXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOUoOSG9sZGluZ19VbmxvY2tSe3J5CncKQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGg5Ib2xkaW5nX1VubG9ja1gBYgEyapoDcpcDCn4KQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGhVIb2xkaW5nX1VubG9ja19SZXN1bHQSUgoKaG9sZGluZ0NpZBJESkIwMDlkMDc4ZjU2Y2M1MzFjMzJhZjc1Nzk5ZDM1YjJhY2M1ZTNlNjVhMWY4ZDU3Y2ZjMGNhNmQyZDRmNDA0MDEwNGMSwAEKBG1ldGEStwFStAEKsQFyrgEKaQpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGghNZXRhZGF0YRJBCgZ2YWx1ZXMSN2I1CjMKJ3NwbGljZS5sZmRlY2VudHJhbGl6ZWR0cnVzdC5vcmcvdHgta2luZBIIQgZ1bmxvY2sa6Q4KATDCPuIOGt8OCgMyLjESigEwMDU4ZTY4ODJmOTk4OWMzZWNhOTc3MDM2ZWYzYmE5YTAwM2VjYzBhZmNmMmFiNDdlMWJkODk3ZDIxZmM3NTBhMzNjYTEyMTIyMGNjMzk5ZjRiYWQxOTllMmI3MmU2ZGU4YTZiZWFhMjY1OWEwNzc0MzcyZTQxNDczNDI1MzFlNWZiYjNjYzI1NzYaE3V0aWxpdHktcmVnaXN0cnktdjAifApAYTIzNmU4ZTIyYTNiNWYxOTllMzdkNTU1NGU4MmJhZmQyZGY2ODhmOTAxZGUwMmIwMGJlMzk2NGJkZmE4YzFhYhImVXRpbGl0eS5SZWdpc3RyeS5WMC5Ib2xkaW5nLkFsbG9jYXRpb24aEER2cExlZ0FsbG9jYXRpb24qaGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5KldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIyaGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5MldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIyVHJhdmktbmV3LXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyQm0KQDkzYzk0MmFlMmI0YzJiYTY3NGZiMTUyZmUzODQ3M2M1MDdiZGE0ZTgyYjRlNGM1ZGE1NWE1NTJhOWQ4Y2NlMWQSHVNwbGljZS5BcGkuVG9rZW4uQWxsb2NhdGlvblYxGgpBbGxvY2F0aW9uShNBbGxvY2F0aW9uX1dpdGhkcmF3UpAEco0ECnYKQDkzYzk0MmFlMmI0YzJiYTY3NGZiMTUyZmUzODQ3M2M1MDdiZGE0ZTgyYjRlNGM1ZGE1NWE1NTJhOWQ4Y2NlMWQSHVNwbGljZS5BcGkuVG9rZW4uQWxsb2NhdGlvblYxGhNBbGxvY2F0aW9uX1dpdGhkcmF3EpIDCglleHRyYUFyZ3MShANygQMKagpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGglFeHRyYUFyZ3MSjAEKB2NvbnRleHQSgAFyfgpuCkA0ZGVkNmI2NjhjYjNiNjRmN2E4OGEzMDg3NGNkNDFjNzU4MjlmNWUwNjRiM2ZiYmFkZjQxZWM3ZTgzNjMzNTRmEhtTcGxpY2UuQXBpLlRva2VuLk1ldGFkYXRhVjEaDUNob2ljZUNvbnRleHQSDAoGdmFsdWVzEgJiABKDAQoEbWV0YRJ7cnkKaQpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGghNZXRhZGF0YRIMCgZ2YWx1ZXMSAmIAWAFiATFq5gJy4wIKfApAOTNjOTQyYWUyYjRjMmJhNjc0ZmIxNTJmZTM4NDczYzUwN2JkYTRlODJiNGU0YzVkYTU1YTU1MmE5ZDhjY2UxZBIdU3BsaWNlLkFwaS5Ub2tlbi5BbGxvY2F0aW9uVjEaGUFsbG9jYXRpb25fV2l0aGRyYXdSZXN1bHQSXQoRc2VuZGVySG9sZGluZ0NpZHMSSFpGCkRKQjAwOWQwNzhmNTZjYzUzMWMzMmFmNzU3OTlkMzViMmFjYzVlM2U2NWExZjhkNTdjZmMwY2E2ZDJkNGY0MDQwMTA0YxKDAQoEbWV0YRJ7cnkKaQpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGghNZXRhZGF0YRIMCgZ2YWx1ZXMSAmIAIiISIFDXBkCsHISv6TSR61NjuH1sRlGw8kmierVx8gd7PE8OIiQIARIgqOxVK34xLjQNK6LRQ7EpZ4uhGxAXPWcOlbQXq3W7MZ4iJAgCEiDYQjAInUHjw62Pd2y6yLhAeUy75pElVXdCGNxx6kWO2xK8QhJ/CldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDISJDQwYjQ4NWFhLWQ1NzktNDVmZC1iMjJiLWRiNWU4YjBiODJkZBpTZ2xvYmFsLWRvbWFpbjo6MTIyMGJlNThjMjllNjVkZTQwYmYyNzNiZTFkYzJiMjY2ZDQzYTlhMDAyZWE1YjE4OTU1YWVlZjdhYWM4ODFiYjQ3MWEqJGYyZmJhOGUzLTkwMmMtNDg1OS1iODBiLWE4YzZiMTE3ZWRjMDCBp9uZvdaUAzq7JQrKGAoDMi4xEooBMDA1OGU2ODgyZjk5ODljM2VjYTk3NzAzNmVmM2JhOWEwMDNlY2MwYWZjZjJhYjQ3ZTFiZDg5N2QyMWZjNzUwYTMzY2ExMjEyMjBjYzM5OWY0YmFkMTk5ZTJiNzJlNmRlOGE2YmVhYTI2NTlhMDc3NDM3MmU0MTQ3MzQyNTMxZTVmYmIzY2MyNTc2GhN1dGlsaXR5LXJlZ2lzdHJ5LXYwInwKQGEyMzZlOGUyMmEzYjVmMTk5ZTM3ZDU1NTRlODJiYWZkMmRmNjg4ZjkwMWRlMDJiMDBiZTM5NjRiZGZhOGMxYWISJlV0aWxpdHkuUmVnaXN0cnkuVjAuSG9sZGluZy5BbGxvY2F0aW9uGhBEdnBMZWdBbGxvY2F0aW9uKsYScsMSCnwKQGEyMzZlOGUyMmEzYjVmMTk5ZTM3ZDU1NTRlODJiYWZkMmRmNjg4ZjkwMWRlMDJiMDBiZTM5NjRiZGZhOGMxYWISJlV0aWxpdHkuUmVnaXN0cnkuVjAuSG9sZGluZy5BbGxvY2F0aW9uGhBEdnBMZWdBbGxvY2F0aW9uEqkOCgphbGxvY2F0aW9uEpoOcpcOCnoKQDkzYzk0MmFlMmI0YzJiYTY3NGZiMTUyZmUzODQ3M2M1MDdiZGE0ZTgyYjRlNGM1ZGE1NWE1NTJhOWQ4Y2NlMWQSHVNwbGljZS5BcGkuVG9rZW4uQWxsb2NhdGlvblYxGhdBbGxvY2F0aW9uU3BlY2lmaWNhdGlvbhLmBgoKc2V0dGxlbWVudBLXBnLUBgpxCkA5M2M5NDJhZTJiNGMyYmE2NzRmYjE1MmZlMzg0NzNjNTA3YmRhNGU4MmI0ZTRjNWRhNTVhNTUyYTlkOGNjZTFkEh1TcGxpY2UuQXBpLlRva2VuLkFsbG9jYXRpb25WMRoOU2V0dGxlbWVudEluZm8SYgoIZXhlY3V0b3ISVjpUcmF2aS1uZXctcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyErgCCg1zZXR0bGVtZW50UmVmEqYCcqMCCmwKQDkzYzk0MmFlMmI0YzJiYTY3NGZiMTUyZmUzODQ3M2M1MDdiZGE0ZTgyYjRlNGM1ZGE1NWE1NTJhOWQ4Y2NlMWQSHVNwbGljZS5BcGkuVG9rZW4uQWxsb2NhdGlvblYxGglSZWZlcmVuY2USFQoCaWQSD0INQ0FTSC0yN0JERUY2NBKbAQoDY2lkEpMBUpABCo0BSooBMDAyMDEwOGI3YWVlMGUwMjE1NTM4NjY4YTdlYmIwMGU3ZTgxMTEzNWZmMmViZjIzMTM3NzYwMDU2ZTA3N2I5MzQ3Y2ExMjEyMjBkZmEyNWNkOTA1Y2FiYTAxMzQ1YjUxNWQxMDAyYWY5NGIwYmEyYTljMmU5YTY3NTFjMDdlZDI4Nzk1NDU0YTllEhgKC3JlcXVlc3RlZEF0EgkpALNldrNSBgASGwoOYWxsb2NhdGVCZWZvcmUSCSnogZe/s1IGABIZCgxzZXR0bGVCZWZvcmUSCSnoU+EqtFIGABLtAQoEbWV0YRLkAXLhAQppCkA0ZGVkNmI2NjhjYjNiNjRmN2E4OGEzMDg3NGNkNDFjNzU4MjlmNWUwNjRiM2ZiYmFkZjQxZWM3ZTgzNjMzNTRmEhtTcGxpY2UuQXBpLlRva2VuLk1ldGFkYXRhVjEaCE1ldGFkYXRhEnQKBnZhbHVlcxJqYmgKJgoTY29tLmJpdGdvL3RyYWRlLXJlZhIPQg1DQVNILTI3QkRFRjY0Cj4KJnNwbGljZS5sZmRlY2VudHJhbGl6ZWR0cnVzdC5vcmcvcmVhc29uEhRCEkNhc2hEdnAgYWxsb2NhdGlvbhItCg10cmFuc2ZlckxlZ0lkEhxCGkNBU0gtMjdCREVGNjQtc2VjdXJpdHktbGVnEoAGCgt0cmFuc2ZlckxlZxLwBXLtBQpuCkA5M2M5NDJhZTJiNGMyYmE2NzRmYjE1MmZlMzg0NzNjNTA3YmRhNGU4MmI0ZTRjNWRhNTVhNTUyYTlkOGNjZTFkEh1TcGxpY2UuQXBpLlRva2VuLkFsbG9jYXRpb25WMRoLVHJhbnNmZXJMZWcSYwoGc2VuZGVyElk6V3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMhJpCghyZWNlaXZlchJdOltyYXZpLTItc3RlcC1wYXJ0eS1uZXc6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyEhgKBmFtb3VudBIOMgw1LjAwMDAwMDAwMDASigIKDGluc3RydW1lbnRJZBL5AXL2AQpsCkA3MThhMGY3N2U1MDVhOGRlMjJmMTg4YmQ0Yzg3ZmU3NDEwMTI3NGU5ZDRjYjFiZmFjN2QwOWFlYzcxNThkMzViEhpTcGxpY2UuQXBpLlRva2VuLkhvbGRpbmdWMRoMSW5zdHJ1bWVudElkEnMKBWFkbWluEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EhEKAmlkEgtCCVRlc3RUb2tlbhKDAQoEbWV0YRJ7cnkKaQpANGRlZDZiNjY4Y2IzYjY0ZjdhODhhMzA4NzRjZDQxYzc1ODI5ZjVlMDY0YjNmYmJhZGY0MWVjN2U4MzYzMzU0ZhIbU3BsaWNlLkFwaS5Ub2tlbi5NZXRhZGF0YVYxGghNZXRhZGF0YRIMCgZ2YWx1ZXMSAmIAEqIBChBsb2NrZWRIb2xkaW5nQ2lkEo0BSooBMDA3Nzg2OWM2NTM2ODRmN2ZiNDNmMmFiNzkyZDNmZGExNWJhNmNkMzFlNWFjN2Q1ZmUwMzJhN2M3ODgzNDRjZDE1Y2ExMjEyMjBhOTQyZTVjNzM0MjliZmQ2NGYzMTExZDc2NzE4OWU3ZGM2M2E5YjlkMWE3ZTI4OGUzOTFjMzBjOGQwY2RiZmMzEnYKCG9wZXJhdG9yEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EnoKCHByb3ZpZGVyEm5SbApqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOTJoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkyV3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4Zjk6V3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjpUcmF2aS1uZXctcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQywD6nq7D1t9aUA9I+4AwKAzIuMRLYDApFAFjmiC+ZicPsqXcDbvO6mgA+zAr88qtH4b2JfSH8dQozyhISIMw5n0utGZ4rcubeimvqomWaB3Q3LkFHNCUx5fuzzCV2EhN1dGlsaXR5LXJlZ2lzdHJ5LXYwGoABCkBhMjM2ZThlMjJhM2I1ZjE5OWUzN2Q1NTU0ZTgyYmFmZDJkZjY4OGY5MDFkZTAyYjAwYmUzOTY0YmRmYThjMWFiEgdVdGlsaXR5EghSZWdpc3RyeRICVjASB0hvbGRpbmcSCkFsbG9jYXRpb24aEER2cExlZ0FsbG9jYXRpb24iqAhqpQgK9wUK9AVq8QUK5AIK4QJq3gIKWApWOlRyYXZpLW5ldy1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIKZgpkamIKEQoPQg1DQVNILTI3QkRFRjY0Ck0KS1JJCkdKRQAgEIt67g4CFVOGaKfrsA5+gRE1/y6/IxN3YAVuB3uTR8oSEiDfolzZBcq6ATRbUV0QAq+UsLoqnC6aZ1HAftKHlUVKngoLCgkpALNldrNSBgAKCwoJKeiBl7+zUgYACgsKCSnoU+EqtFIGAApzCnFqbwptCmuCAWgKJgoTY29tLmJpdGdvL3RyYWRlLXJlZhIPQg1DQVNILTI3QkRFRjY0Cj4KJnNwbGljZS5sZmRlY2VudHJhbGl6ZWR0cnVzdC5vcmcvcmVhc29uEhRCEkNhc2hEdnAgYWxsb2NhdGlvbgoeChxCGkNBU0gtMjdCREVGNjQtc2VjdXJpdHktbGVnCucCCuQCauECClsKWTpXcmF2aS0yLXN0ZXAtcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyCl8KXTpbcmF2aS0yLXN0ZXAtcGFydHktbmV3OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMgoQCg4yDDUuMDAwMDAwMDAwMAqBAQp/an0KbApqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOQoNCgtCCVRlc3RUb2tlbgoLCglqBwoFCgOCAQAKSQpHSkUAd4acZTaE9/tD8qt5LT/aFbps0x5ax9X+Ayp8eINEzRXKEhIgqULlxzQpv9ZPMRHXZxiefcY6m50afiiOORwwyNDNv8MKbApqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOQpwCm5SbApqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOSpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkqV3JhdmktMi1zdGVwLXBhcnR5OjoxMjIwOTJlN2QzM2FjMTBjMGYzZDU1OTc2MzQyZjM3NTU1ZGYwNWRhNWI3NDI5NTZkNTZhNjJhZTIzNjc3NjkwNzlkMjJUcmF2aS1uZXctcGFydHk6OjEyMjA5MmU3ZDMzYWMxMGMwZjNkNTU5NzYzNDJmMzc1NTVkZjA1ZGE1Yjc0Mjk1NmQ1NmE2MmFlMjM2Nzc2OTA3OWQyOacVrH6zUgYAQioKJgokCAESIDPiBjJV0ksK5Z32T00SN1kfSU4PHzfrg0UmIWe75M5dEB469hoKrhAKAzIuMRKKATAwNzc4NjljNjUzNjg0ZjdmYjQzZjJhYjc5MmQzZmRhMTViYTZjZDMxZTVhYzdkNWZlMDMyYTdjNzg4MzQ0Y2QxNWNhMTIxMjIwYTk0MmU1YzczNDI5YmZkNjRmMzExMWQ3NjcxODllN2RjNjNhOWI5ZDFhN2UyODhlMzkxYzMwYzhkMGNkYmZjMxobdXRpbGl0eS1yZWdpc3RyeS1ob2xkaW5nLXYwInAKQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGgdIb2xkaW5nKoQLcoELCnAKQDgxMDc4OTlhYzQ3MjNjZTk4NmJmN2QyNzQxNjUzNGU1NzZlNTRiOTIxNjFlNDYxNTBhNTk1ZmI3OGZmM2QzYTESI1V0aWxpdHkuUmVnaXN0cnkuSG9sZGluZy5WMC5Ib2xkaW5nGgdIb2xkaW5nEnYKCG9wZXJhdG9yEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EnYKCHByb3ZpZGVyEmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5EncKCXJlZ2lzdHJhchJqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmORJiCgVvd25lchJZOldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDISvQIKCmluc3RydW1lbnQSrgJyqwIKewpAODEwNzg5OWFjNDcyM2NlOTg2YmY3ZDI3NDE2NTM0ZTU3NmU1NGI5MjE2MWU0NjE1MGE1OTVmYjc4ZmYzZDNhMRIhVXRpbGl0eS5SZWdpc3RyeS5Ib2xkaW5nLlYwLlR5cGVzGhRJbnN0cnVtZW50SWRlbnRpZmllchJ0CgZzb3VyY2USajpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkSEQoCaWQSC0IJVGVzdFRva2VuEiMKBnNjaGVtZRIZQhdSZWdpc3RyYXJJbnRlcm5hbFNjaGVtZRILCgVsYWJlbBICQgASGAoGYW1vdW50Eg4yDDUuMDAwMDAwMDAwMBLYAwoEbG9jaxLPA1LMAwrJA3LGAwptCkA4MTA3ODk5YWM0NzIzY2U5ODZiZjdkMjc0MTY1MzRlNTc2ZTU0YjkyMTYxZTQ2MTUwYTU5NWZiNzhmZjNkM2ExEiNVdGlsaXR5LlJlZ2lzdHJ5LkhvbGRpbmcuVjAuSG9sZGluZxoETG9jaxLjAQoHbG9ja2VycxLXAXLUAQpVCkBjM2JiMGM1ZDA0Nzk5YjNmMTFiYWQ3YzNjMTAyOTYzZTExNWNmNTNkYTNlNGFmY2JjZmQ5ZjA2ZWJkODJiNGZmEgxEQS5TZXQuVHlwZXMaA1NldBJ7CgNtYXASdGpyCnAKajpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkSAgoAEm8KB2NvbnRleHQSZEJiQWxsb2NhdGlvbiBSZWZlcmVuY2Uge2lkID0gIkNBU0gtMjdCREVGNjQiLCBjaWQgPSBTb21lIDxjb250cmFjdC1pZD59OyJDQVNILTI3QkRFRjY0LXNlY3VyaXR5LWxlZyIyaGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5MldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDI6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5OldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDLAPqersPW31pQD0j63CgoDMi4xEq8KCkUAd4acZTaE9/tD8qt5LT/aFbps0x5ax9X+Ayp8eINEzRXKEhIgqULlxzQpv9ZPMRHXZxiefcY6m50afiiOORwwyNDNv8MSG3V0aWxpdHktcmVnaXN0cnktaG9sZGluZy12MBp0CkA4MTA3ODk5YWM0NzIzY2U5ODZiZjdkMjc0MTY1MzRlNTc2ZTU0YjkyMTYxZTQ2MTUwYTU5NWZiNzhmZjNkM2ExEgdVdGlsaXR5EghSZWdpc3RyeRIHSG9sZGluZxICVjASB0hvbGRpbmcaB0hvbGRpbmci2gZq1wYKbApqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOQpsCmo6aGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5CmwKajpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkKWwpZOldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDIKoAEKnQFqmgEKbApqOmhhdXRoMF8wMDdjNjVmODU3ZjFjM2Q1OTljYjZkZjczNzc1OjoxMjIwZDJkNzMyZDA0MmMyODFjZWU4MGY0ODNhYjgwZjNjYmFhNDc4Mjg2MGVkNWY0ZGMyMjhhYjAzZGVkZDJlZThmOQoNCgtCCVRlc3RUb2tlbgobChlCF1JlZ2lzdHJhckludGVybmFsU2NoZW1lCgQKAkIAChAKDjIMNS4wMDAwMDAwMDAwCvIBCu8BUuwBCukBauYBCnwKemp4CnYKdGJyCnAKajpoYXV0aDBfMDA3YzY1Zjg1N2YxYzNkNTk5Y2I2ZGY3Mzc3NTo6MTIyMGQyZDczMmQwNDJjMjgxY2VlODBmNDgzYWI4MGYzY2JhYTQ3ODI4NjBlZDVmNGRjMjI4YWIwM2RlZGQyZWU4ZjkSAgoACmYKZEJiQWxsb2NhdGlvbiBSZWZlcmVuY2Uge2lkID0gIkNBU0gtMjdCREVGNjQiLCBjaWQgPSBTb21lIDxjb250cmFjdC1pZD59OyJDQVNILTI3QkRFRjY0LXNlY3VyaXR5LWxlZyIqaGF1dGgwXzAwN2M2NWY4NTdmMWMzZDU5OWNiNmRmNzM3NzU6OjEyMjBkMmQ3MzJkMDQyYzI4MWNlZTgwZjQ4M2FiODBmM2NiYWE0NzgyODYwZWQ1ZjRkYzIyOGFiMDNkZWRkMmVlOGY5KldyYXZpLTItc3RlcC1wYXJ0eTo6MTIyMDkyZTdkMzNhYzEwYzBmM2Q1NTk3NjM0MmYzNzU1NWRmMDVkYTViNzQyOTU2ZDU2YTYyYWUyMzY3NzY5MDc5ZDI5pxWsfrNSBgBCKgomCiQIARIgBFNlzJyKvRF6uO0zEHo4MOvIHhahTB2E/7iYfH1X01cQHg==', diff --git a/modules/sdk-coin-canton/test/unit/builder/allocationReject/allocationRejectBuilder.ts b/modules/sdk-coin-canton/test/unit/builder/allocationReject/allocationRejectBuilder.ts new file mode 100644 index 0000000000..6339d822f3 --- /dev/null +++ b/modules/sdk-coin-canton/test/unit/builder/allocationReject/allocationRejectBuilder.ts @@ -0,0 +1,133 @@ +import assert from 'assert'; +import should from 'should'; + +import { coins } from '@bitgo/statics'; + +import { AllocationRejectBuilder, Transaction } from '../../../../src'; +import { CantonTransferAcceptRejectRequest } from '../../../../src/lib/iface'; + +import { AllocationRejection, CantonAllocationRejectPrepareResponse } from '../../../resources'; + +describe('AllocationReject Builder', () => { + it('should get the allocation reject request object', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + txBuilder.setTransaction(CantonAllocationRejectPrepareResponse); + const { commandId, contractId, partyId } = AllocationRejection; + txBuilder.commandId(commandId).contractId(contractId).actAs(partyId); + const requestObj: CantonTransferAcceptRejectRequest = txBuilder.toRequestObject(); + should.exist(requestObj); + assert.equal(requestObj.commandId, commandId); + assert.equal(requestObj.contractId, contractId); + assert.equal(requestObj.actAs.length, 1); + assert.equal(requestObj.actAs[0], partyId); + assert.equal(requestObj.verboseHashing, false); + assert.deepEqual(requestObj.readAs, []); + }); + + it('should set the transaction id to the commandId', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + const { commandId } = AllocationRejection; + txBuilder.commandId(commandId); + assert.equal(tx.id, commandId); + }); + + it('should validate raw canton allocation reject transaction', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + txBuilder.setTransaction(CantonAllocationRejectPrepareResponse); + txBuilder.validateRawTransaction(CantonAllocationRejectPrepareResponse.preparedTransaction); + }); + + it('should validate the transaction', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + tx.prepareCommand = CantonAllocationRejectPrepareResponse; + txBuilder.initBuilder(tx); + txBuilder.setTransaction(CantonAllocationRejectPrepareResponse); + txBuilder.validateTransaction(tx); + }); + + it('should throw error on invalid raw transaction hash mismatch', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + const invalidPrepareResponse = { + ...CantonAllocationRejectPrepareResponse, + preparedTransactionHash: 'L1KfrA5exnpsOqtXODGj2gNF+y/dv/onPtVvGJ5km7d=', + }; + txBuilder.setTransaction(invalidPrepareResponse); + try { + txBuilder.validateRawTransaction(invalidPrepareResponse.preparedTransaction); + } catch (e) { + assert.equal(e.message, 'invalid raw transaction, hash not matching'); + } + }); + + it('should throw if commandId is missing', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + const { contractId, partyId } = AllocationRejection; + txBuilder.contractId(contractId).actAs(partyId); + assert.throws(() => txBuilder.toRequestObject(), /commandId is missing/); + }); + + it('should throw if contractId is missing', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + const { commandId, partyId } = AllocationRejection; + txBuilder.commandId(commandId).actAs(partyId); + assert.throws(() => txBuilder.toRequestObject(), /contractId is missing/); + }); + + it('should throw if actAs is missing', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + const { commandId, contractId } = AllocationRejection; + txBuilder.commandId(commandId).contractId(contractId); + assert.throws(() => txBuilder.toRequestObject(), /actAs partyId is missing/); + }); + + it('should throw if commandId is an empty string', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + assert.throws(() => txBuilder.commandId(''), /commandId must be a non-empty string/); + }); + + it('should throw if contractId is an empty string', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + assert.throws(() => txBuilder.contractId(''), /contractId must be a non-empty string/); + }); + + it('should throw if actAs is an empty string', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + assert.throws(() => txBuilder.actAs(''), /actAsPartyId must be a non-empty string/); + }); + + describe('Prepared transaction parsing', () => { + it('should parse the allocation reject prepared transaction', function () { + const txBuilder = new AllocationRejectBuilder(coins.get('tcanton')); + const tx = new Transaction(coins.get('tcanton')); + txBuilder.initBuilder(tx); + txBuilder.commandId(AllocationRejection.commandId); + txBuilder.setTransaction(CantonAllocationRejectPrepareResponse); + const txData = txBuilder.transaction.toJson(); + should.exist(txData); + // seller = rejecting party (sender) + assert.equal( + txData.sender, + 'ravi-2-step-party::122092e7d33ac10c0f3d55976342f37555df05da5b742956d56a62ae2367769079d2' + ); + // buyer = counterparty (receiver) + assert.equal(txData.receiver, '12208::122083082e9af156feaeb7afd363a0ee5ffa1fd160947b647a139a7e0c2ed78f5dc7'); + // amount from dvp.terms.deliveries[0] (converted to lowest unit: 2.0 * 10^10 = 20000000000) + assert.equal(txData.amount, '20000000000'); + }); + }); +}); diff --git a/modules/sdk-core/src/account-lib/baseCoin/enum.ts b/modules/sdk-core/src/account-lib/baseCoin/enum.ts index 05248d5d74..310975b1b2 100644 --- a/modules/sdk-core/src/account-lib/baseCoin/enum.ts +++ b/modules/sdk-core/src/account-lib/baseCoin/enum.ts @@ -107,6 +107,8 @@ export enum TransactionType { AllocationAllocateWithdrawn, // canton allocation request (internal/dummy txRequest surfacing DvP trade details to the allocating party) AllocationRequest, + // canton allocation reject + AllocationReject, // canton generic DAML command CantonCommand,