@hsuite/native-connect-angular 1.0.0
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/README.md +48 -0
- package/USAGE_EXAMPLES.md +476 -0
- package/assets/wallets/extension.svg +7 -0
- package/assets/wallets/hashpack.svg +6 -0
- package/assets/wallets/hsuite.svg +11 -0
- package/assets/wallets/kabila.svg +11 -0
- package/assets/wallets/walletconnect.svg +13 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-summary.json +50 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +476 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +476 -0
- package/coverage/lcov-report/lib/components/account-selector/account-actions/account-actions.component.ts.html +868 -0
- package/coverage/lcov-report/lib/components/account-selector/account-actions/index.html +116 -0
- package/coverage/lcov-report/lib/components/account-selector/account-filter/account-filter.component.ts.html +1288 -0
- package/coverage/lcov-report/lib/components/account-selector/account-filter/index.html +116 -0
- package/coverage/lcov-report/lib/components/account-selector/account-formatting.service.ts.html +685 -0
- package/coverage/lcov-report/lib/components/account-selector/account-grouping.service.ts.html +766 -0
- package/coverage/lcov-report/lib/components/account-selector/account-list/account-list.component.ts.html +1495 -0
- package/coverage/lcov-report/lib/components/account-selector/account-list/index.html +116 -0
- package/coverage/lcov-report/lib/components/account-selector/account-selector.component.ts.html +1495 -0
- package/coverage/lcov-report/lib/components/account-selector/account-selector.service.ts.html +1588 -0
- package/coverage/lcov-report/lib/components/account-selector/index.html +161 -0
- package/coverage/lcov-report/lib/components/wallet-account-display/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-account-display/wallet-account-display.component.ts.html +505 -0
- package/coverage/lcov-report/lib/components/wallet-connect-button/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +805 -0
- package/coverage/lcov-report/lib/components/wallet-connect-prompt/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +409 -0
- package/coverage/lcov-report/lib/components/wallet-connected-guard/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +304 -0
- package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +436 -0
- package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-connection-modal/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +2287 -0
- package/coverage/lcov-report/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +2275 -0
- package/coverage/lcov-report/lib/components/wallet-session-display/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-session-display/wallet-session-display.component.ts.html +676 -0
- package/coverage/lcov-report/lib/components/wallet-transaction-status/index.html +116 -0
- package/coverage/lcov-report/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +703 -0
- package/coverage/lcov-report/lib/directives/index.html +146 -0
- package/coverage/lcov-report/lib/directives/wallet-connected.directive.ts.html +670 -0
- package/coverage/lcov-report/lib/directives/wallet-context.directive.ts.html +547 -0
- package/coverage/lcov-report/lib/directives/wallet-events.directive.ts.html +781 -0
- package/coverage/lcov-report/lib/hsuite-wallet.module.ts.html +715 -0
- package/coverage/lcov-report/lib/index.html +116 -0
- package/coverage/lcov-report/lib/models/connection-config.model.ts.html +280 -0
- package/coverage/lcov-report/lib/models/index.html +131 -0
- package/coverage/lcov-report/lib/models/provider-types.ts.html +577 -0
- package/coverage/lcov-report/lib/providers/base-wallet-provider.ts.html +1138 -0
- package/coverage/lcov-report/lib/providers/hsuite-native/channel-client.service.ts.html +2671 -0
- package/coverage/lcov-report/lib/providers/hsuite-native/index.html +116 -0
- package/coverage/lcov-report/lib/providers/hsuite-native-provider.ts.html +2347 -0
- package/coverage/lcov-report/lib/providers/index.html +146 -0
- package/coverage/lcov-report/lib/providers/p2p-native/index.html +131 -0
- package/coverage/lcov-report/lib/providers/p2p-native/p2p-native.provider.ts.html +2254 -0
- package/coverage/lcov-report/lib/providers/p2p-native/p2p-session-manager.ts.html +2170 -0
- package/coverage/lcov-report/lib/providers/wallet-error-handler.ts.html +1132 -0
- package/coverage/lcov-report/lib/providers/walletconnect/core/index.html +176 -0
- package/coverage/lcov-report/lib/providers/walletconnect/core/session-health.ts.html +673 -0
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +1177 -0
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-provider.ts.html +2563 -0
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +904 -0
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +982 -0
- package/coverage/lcov-report/lib/providers/walletconnect/signers/hedera-signer.ts.html +1915 -0
- package/coverage/lcov-report/lib/providers/walletconnect/signers/index.html +146 -0
- package/coverage/lcov-report/lib/providers/walletconnect/signers/signer-factory.ts.html +445 -0
- package/coverage/lcov-report/lib/providers/walletconnect/signers/xrpl-signer.ts.html +1519 -0
- package/coverage/lcov-report/lib/services/index.html +191 -0
- package/coverage/lcov-report/lib/services/logger.service.ts.html +463 -0
- package/coverage/lcov-report/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1840 -0
- package/coverage/lcov-report/lib/services/transaction-builders/hedera-amount-utils.ts.html +337 -0
- package/coverage/lcov-report/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +3940 -0
- package/coverage/lcov-report/lib/services/transaction-builders/index.html +161 -0
- package/coverage/lcov-report/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +2581 -0
- package/coverage/lcov-report/lib/services/transaction.service.ts.html +1123 -0
- package/coverage/lcov-report/lib/services/unified-wallet.service.ts.html +2641 -0
- package/coverage/lcov-report/lib/services/wallet-context.service.ts.html +637 -0
- package/coverage/lcov-report/lib/services/wallet-event-bus.service.ts.html +643 -0
- package/coverage/lcov-report/lib/services/wallet-providers.service.ts.html +496 -0
- package/coverage/lcov-report/lib/transports/chrome-extension-transport.ts.html +823 -0
- package/coverage/lcov-report/lib/transports/index.html +116 -0
- package/coverage/lcov-report/lib/utils/index.html +116 -0
- package/coverage/lcov-report/lib/utils/ledger-icons.util.ts.html +319 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +19252 -0
- package/coverage/lib/components/account-selector/account-actions/account-actions.component.ts.html +868 -0
- package/coverage/lib/components/account-selector/account-actions/index.html +116 -0
- package/coverage/lib/components/account-selector/account-filter/account-filter.component.ts.html +1288 -0
- package/coverage/lib/components/account-selector/account-filter/index.html +116 -0
- package/coverage/lib/components/account-selector/account-formatting.service.ts.html +685 -0
- package/coverage/lib/components/account-selector/account-grouping.service.ts.html +766 -0
- package/coverage/lib/components/account-selector/account-list/account-list.component.ts.html +1495 -0
- package/coverage/lib/components/account-selector/account-list/index.html +116 -0
- package/coverage/lib/components/account-selector/account-selector.component.ts.html +1495 -0
- package/coverage/lib/components/account-selector/account-selector.service.ts.html +1588 -0
- package/coverage/lib/components/account-selector/index.html +161 -0
- package/coverage/lib/components/wallet-account-display/index.html +116 -0
- package/coverage/lib/components/wallet-account-display/wallet-account-display.component.ts.html +505 -0
- package/coverage/lib/components/wallet-connect-button/index.html +116 -0
- package/coverage/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +805 -0
- package/coverage/lib/components/wallet-connect-prompt/index.html +116 -0
- package/coverage/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +409 -0
- package/coverage/lib/components/wallet-connected-guard/index.html +116 -0
- package/coverage/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +304 -0
- package/coverage/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +436 -0
- package/coverage/lib/components/wallet-connection-modal/connection-method-step/index.html +116 -0
- package/coverage/lib/components/wallet-connection-modal/index.html +116 -0
- package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/index.html +116 -0
- package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +2287 -0
- package/coverage/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +2275 -0
- package/coverage/lib/components/wallet-session-display/index.html +116 -0
- package/coverage/lib/components/wallet-session-display/wallet-session-display.component.ts.html +676 -0
- package/coverage/lib/components/wallet-transaction-status/index.html +116 -0
- package/coverage/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +703 -0
- package/coverage/lib/directives/index.html +146 -0
- package/coverage/lib/directives/wallet-connected.directive.ts.html +670 -0
- package/coverage/lib/directives/wallet-context.directive.ts.html +547 -0
- package/coverage/lib/directives/wallet-events.directive.ts.html +781 -0
- package/coverage/lib/hsuite-wallet.module.ts.html +715 -0
- package/coverage/lib/index.html +116 -0
- package/coverage/lib/models/connection-config.model.ts.html +280 -0
- package/coverage/lib/models/index.html +131 -0
- package/coverage/lib/models/provider-types.ts.html +577 -0
- package/coverage/lib/providers/base-wallet-provider.ts.html +1138 -0
- package/coverage/lib/providers/hsuite-native/channel-client.service.ts.html +2671 -0
- package/coverage/lib/providers/hsuite-native/index.html +116 -0
- package/coverage/lib/providers/hsuite-native-provider.ts.html +2347 -0
- package/coverage/lib/providers/index.html +146 -0
- package/coverage/lib/providers/p2p-native/index.html +131 -0
- package/coverage/lib/providers/p2p-native/p2p-native.provider.ts.html +2254 -0
- package/coverage/lib/providers/p2p-native/p2p-session-manager.ts.html +2170 -0
- package/coverage/lib/providers/wallet-error-handler.ts.html +1132 -0
- package/coverage/lib/providers/walletconnect/core/index.html +176 -0
- package/coverage/lib/providers/walletconnect/core/session-health.ts.html +673 -0
- package/coverage/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +1177 -0
- package/coverage/lib/providers/walletconnect/core/walletconnect-provider.ts.html +2563 -0
- package/coverage/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +904 -0
- package/coverage/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +982 -0
- package/coverage/lib/providers/walletconnect/signers/hedera-signer.ts.html +1915 -0
- package/coverage/lib/providers/walletconnect/signers/index.html +146 -0
- package/coverage/lib/providers/walletconnect/signers/signer-factory.ts.html +445 -0
- package/coverage/lib/providers/walletconnect/signers/xrpl-signer.ts.html +1519 -0
- package/coverage/lib/services/index.html +191 -0
- package/coverage/lib/services/logger.service.ts.html +463 -0
- package/coverage/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1840 -0
- package/coverage/lib/services/transaction-builders/hedera-amount-utils.ts.html +337 -0
- package/coverage/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +3940 -0
- package/coverage/lib/services/transaction-builders/index.html +161 -0
- package/coverage/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +2581 -0
- package/coverage/lib/services/transaction.service.ts.html +1123 -0
- package/coverage/lib/services/unified-wallet.service.ts.html +2641 -0
- package/coverage/lib/services/wallet-context.service.ts.html +637 -0
- package/coverage/lib/services/wallet-event-bus.service.ts.html +643 -0
- package/coverage/lib/services/wallet-providers.service.ts.html +496 -0
- package/coverage/lib/transports/chrome-extension-transport.ts.html +823 -0
- package/coverage/lib/transports/index.html +116 -0
- package/coverage/lib/utils/index.html +116 -0
- package/coverage/lib/utils/ledger-icons.util.ts.html +319 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/README.md +48 -0
- package/dist/fesm2022/hsuite-native-connect-angular.mjs +14592 -0
- package/dist/fesm2022/hsuite-native-connect-angular.mjs.map +1 -0
- package/dist/index.d.ts +6949 -0
- package/examples/minimal-connect.ts +178 -0
- package/examples/multi-protocol.ts +495 -0
- package/examples/transaction-signing.ts +361 -0
- package/jest.config.json +45 -0
- package/karma.conf.js +42 -0
- package/ng-package.json +20 -0
- package/package.json +60 -0
- package/src/index.ts +203 -0
- package/src/lib/components/account-selector/account-actions/account-actions.component.ts +261 -0
- package/src/lib/components/account-selector/account-filter/account-filter.component.ts +401 -0
- package/src/lib/components/account-selector/account-formatting.service.ts +200 -0
- package/src/lib/components/account-selector/account-grouping.service.ts +227 -0
- package/src/lib/components/account-selector/account-list/account-list.component.ts +470 -0
- package/src/lib/components/account-selector/account-selector.component.html +135 -0
- package/src/lib/components/account-selector/account-selector.component.scss +2039 -0
- package/src/lib/components/account-selector/account-selector.component.ts +470 -0
- package/src/lib/components/account-selector/account-selector.service.ts +501 -0
- package/src/lib/components/wallet-account-display/wallet-account-display.component.html +34 -0
- package/src/lib/components/wallet-account-display/wallet-account-display.component.scss +99 -0
- package/src/lib/components/wallet-account-display/wallet-account-display.component.ts +140 -0
- package/src/lib/components/wallet-connect-button/wallet-connect-button.component.html +14 -0
- package/src/lib/components/wallet-connect-button/wallet-connect-button.component.scss +272 -0
- package/src/lib/components/wallet-connect-button/wallet-connect-button.component.ts +240 -0
- package/src/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.html +24 -0
- package/src/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.scss +50 -0
- package/src/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts +108 -0
- package/src/lib/components/wallet-connected-guard/wallet-connected-guard.component.html +24 -0
- package/src/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts +73 -0
- package/src/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.html +56 -0
- package/src/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.scss +218 -0
- package/src/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts +117 -0
- package/src/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.html +94 -0
- package/src/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.scss +272 -0
- package/src/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts +734 -0
- package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.html +197 -0
- package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.scss +678 -0
- package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts +730 -0
- package/src/lib/components/wallet-session-display/wallet-session-display.component.html +110 -0
- package/src/lib/components/wallet-session-display/wallet-session-display.component.scss +179 -0
- package/src/lib/components/wallet-session-display/wallet-session-display.component.ts +197 -0
- package/src/lib/components/wallet-transaction-status/wallet-transaction-status.component.html +65 -0
- package/src/lib/components/wallet-transaction-status/wallet-transaction-status.component.scss +254 -0
- package/src/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts +206 -0
- package/src/lib/directives/wallet-connected.directive.ts +195 -0
- package/src/lib/directives/wallet-context.directive.ts +154 -0
- package/src/lib/directives/wallet-events.directive.ts +232 -0
- package/src/lib/hsuite-wallet.module.ts +210 -0
- package/src/lib/models/connection-config.model.ts +65 -0
- package/src/lib/models/provider-types.ts +164 -0
- package/src/lib/models/unified-account.model.ts +76 -0
- package/src/lib/models/wallet-context.model.ts +121 -0
- package/src/lib/models/wallet-events.model.ts +158 -0
- package/src/lib/providers/base-wallet-provider.ts +351 -0
- package/src/lib/providers/hsuite-native/channel-client.service.spec.ts +73 -0
- package/src/lib/providers/hsuite-native/channel-client.service.ts +862 -0
- package/src/lib/providers/hsuite-native/index.ts +8 -0
- package/src/lib/providers/hsuite-native-provider.ts +754 -0
- package/src/lib/providers/mobile-native/mobile-native.provider.spec.ts +19 -0
- package/src/lib/providers/p2p-native/index.ts +30 -0
- package/src/lib/providers/p2p-native/p2p-native.provider.spec.ts +523 -0
- package/src/lib/providers/p2p-native/p2p-native.provider.ts +723 -0
- package/src/lib/providers/p2p-native/p2p-session-manager.ts +695 -0
- package/src/lib/providers/wallet-error-handler.ts +349 -0
- package/src/lib/providers/walletconnect/core/base-signer.interface.ts +122 -0
- package/src/lib/providers/walletconnect/core/session-health.ts +196 -0
- package/src/lib/providers/walletconnect/core/walletconnect-client-manager.ts +364 -0
- package/src/lib/providers/walletconnect/core/walletconnect-provider.integration.spec.ts +348 -0
- package/src/lib/providers/walletconnect/core/walletconnect-provider.ts +826 -0
- package/src/lib/providers/walletconnect/core/walletconnect-session-store.ts +273 -0
- package/src/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts +299 -0
- package/src/lib/providers/walletconnect/core/walletconnect-types.ts +48 -0
- package/src/lib/providers/walletconnect/index.ts +33 -0
- package/src/lib/providers/walletconnect/signers/hedera-signer.spec.ts +367 -0
- package/src/lib/providers/walletconnect/signers/hedera-signer.ts +610 -0
- package/src/lib/providers/walletconnect/signers/signer-factory.spec.ts +62 -0
- package/src/lib/providers/walletconnect/signers/signer-factory.ts +120 -0
- package/src/lib/providers/walletconnect/signers/xrpl-signer.spec.ts +296 -0
- package/src/lib/providers/walletconnect/signers/xrpl-signer.ts +478 -0
- package/src/lib/services/logger.service.ts +126 -0
- package/src/lib/services/transaction-builders/base-transaction-builder.service.ts +585 -0
- package/src/lib/services/transaction-builders/hedera-amount-utils.ts +84 -0
- package/src/lib/services/transaction-builders/hedera-transaction-builder.service.spec.ts +741 -0
- package/src/lib/services/transaction-builders/hedera-transaction-builder.service.ts +1285 -0
- package/src/lib/services/transaction-builders/index.ts +54 -0
- package/src/lib/services/transaction-builders/xrpl-transaction-builder.service.spec.ts +937 -0
- package/src/lib/services/transaction-builders/xrpl-transaction-builder.service.ts +832 -0
- package/src/lib/services/transaction.service.ts +346 -0
- package/src/lib/services/unified-wallet.service.spec.ts +1382 -0
- package/src/lib/services/unified-wallet.service.ts +852 -0
- package/src/lib/services/wallet-context.service.ts +184 -0
- package/src/lib/services/wallet-event-bus.service.ts +186 -0
- package/src/lib/services/wallet-providers.service.ts +137 -0
- package/src/lib/transports/chrome-extension-transport.ts +246 -0
- package/src/lib/utils/index.ts +14 -0
- package/src/lib/utils/ledger-icons.util.ts +78 -0
- package/test/test-setup.ts +21 -0
- package/test-setup.ts +63 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +29 -0
- package/tsconfig.spec.json +15 -0
- package/vitest.config.ts +48 -0
|
@@ -0,0 +1,937 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Unit tests for XrplTransactionBuilderService
|
|
3
|
+
*
|
|
4
|
+
* Tests cover:
|
|
5
|
+
* - Payment transactions (XRP and tokens)
|
|
6
|
+
* - TrustSet transactions
|
|
7
|
+
* - Offer/DEX transactions (create, cancel)
|
|
8
|
+
* - AccountSet transactions
|
|
9
|
+
* - Escrow transactions (create, finish, cancel)
|
|
10
|
+
* - Payment channel transactions
|
|
11
|
+
* - Check transactions (create, cash, cancel)
|
|
12
|
+
* - DepositPreauth transactions
|
|
13
|
+
* - SignerListSet transactions
|
|
14
|
+
* - TicketCreate transactions
|
|
15
|
+
* - NFT transactions (mint, burn, create/accept/cancel offers)
|
|
16
|
+
* - Batch transactions
|
|
17
|
+
* - Error handling
|
|
18
|
+
*
|
|
19
|
+
* @module services/transaction-builders/xrpl-transaction-builder
|
|
20
|
+
* @since 2.0.0
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { TestBed } from '@angular/core/testing';
|
|
24
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
25
|
+
import { XrplTransactionBuilderService } from './xrpl-transaction-builder.service';
|
|
26
|
+
|
|
27
|
+
describe('XrplTransactionBuilderService', () => {
|
|
28
|
+
let service: XrplTransactionBuilderService;
|
|
29
|
+
|
|
30
|
+
const mockAccount = 'rAccountSourceXXXXXXXXXXXXXX';
|
|
31
|
+
const mockDestination = 'rAccountDestXXXXXXXXXXXXXXX';
|
|
32
|
+
const mockIssuer = 'rIssuerAccountXXXXXXXXXXXXXX';
|
|
33
|
+
|
|
34
|
+
beforeEach(async () => {
|
|
35
|
+
await TestBed.configureTestingModule({
|
|
36
|
+
providers: [XrplTransactionBuilderService],
|
|
37
|
+
}).compileComponents();
|
|
38
|
+
|
|
39
|
+
service = TestBed.inject(XrplTransactionBuilderService);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should create', () => {
|
|
43
|
+
expect(service).toBeTruthy();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Helper to decode and parse base64 transaction
|
|
48
|
+
*/
|
|
49
|
+
function decodeTransaction(base64: string): Record<string, unknown> {
|
|
50
|
+
const json = atob(base64);
|
|
51
|
+
return JSON.parse(json);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ==================== PAYMENT TRANSACTIONS ====================
|
|
55
|
+
describe('buildPayment', () => {
|
|
56
|
+
it('should build XRP payment transaction', async () => {
|
|
57
|
+
const amount = '1000000'; // 1 XRP in drops
|
|
58
|
+
const result = await service.buildPayment(mockAccount, mockDestination, amount);
|
|
59
|
+
|
|
60
|
+
expect(result).toBeDefined();
|
|
61
|
+
expect(typeof result).toBe('string');
|
|
62
|
+
|
|
63
|
+
const tx = decodeTransaction(result);
|
|
64
|
+
expect(tx.TransactionType).toBe('Payment');
|
|
65
|
+
expect(tx.Account).toBe(mockAccount);
|
|
66
|
+
expect(tx.Destination).toBe(mockDestination);
|
|
67
|
+
expect(tx.Amount).toBe(amount);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should build token payment transaction', async () => {
|
|
71
|
+
const amount = '100';
|
|
72
|
+
const currency = 'USD';
|
|
73
|
+
|
|
74
|
+
const result = await service.buildPayment(
|
|
75
|
+
mockAccount,
|
|
76
|
+
mockDestination,
|
|
77
|
+
amount,
|
|
78
|
+
true,
|
|
79
|
+
currency,
|
|
80
|
+
mockIssuer
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const tx = decodeTransaction(result);
|
|
84
|
+
expect(tx.TransactionType).toBe('Payment');
|
|
85
|
+
expect(tx.Account).toBe(mockAccount);
|
|
86
|
+
expect(tx.Destination).toBe(mockDestination);
|
|
87
|
+
expect(tx.Amount).toEqual({
|
|
88
|
+
currency,
|
|
89
|
+
issuer: mockIssuer,
|
|
90
|
+
value: amount,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should default to XRP payment when isToken is false', async () => {
|
|
95
|
+
const amount = '5000000';
|
|
96
|
+
const result = await service.buildPayment(mockAccount, mockDestination, amount, false);
|
|
97
|
+
|
|
98
|
+
const tx = decodeTransaction(result);
|
|
99
|
+
expect(tx.Amount).toBe(amount);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should treat as XRP payment when isToken is true but no currency/issuer provided', async () => {
|
|
103
|
+
const amount = '5000000';
|
|
104
|
+
const result = await service.buildPayment(mockAccount, mockDestination, amount, true);
|
|
105
|
+
|
|
106
|
+
const tx = decodeTransaction(result);
|
|
107
|
+
// When isToken is true but currency/issuer are missing, it falls back to XRP
|
|
108
|
+
expect(tx.Amount).toBe(amount);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// ==================== TRUSTSET TRANSACTIONS ====================
|
|
113
|
+
describe('buildTrustSet', () => {
|
|
114
|
+
it('should build TrustSet transaction', async () => {
|
|
115
|
+
const currency = 'USD';
|
|
116
|
+
const limit = '1000000';
|
|
117
|
+
|
|
118
|
+
const result = await service.buildTrustSet(mockAccount, currency, mockIssuer, limit);
|
|
119
|
+
|
|
120
|
+
const tx = decodeTransaction(result);
|
|
121
|
+
expect(tx.TransactionType).toBe('TrustSet');
|
|
122
|
+
expect(tx.Account).toBe(mockAccount);
|
|
123
|
+
expect(tx.LimitAmount).toEqual({
|
|
124
|
+
currency,
|
|
125
|
+
issuer: mockIssuer,
|
|
126
|
+
value: limit,
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should handle different currency codes', async () => {
|
|
131
|
+
const currencies = ['EUR', 'GBP', 'JPY', 'BTC'];
|
|
132
|
+
|
|
133
|
+
for (const currency of currencies) {
|
|
134
|
+
const result = await service.buildTrustSet(mockAccount, currency, mockIssuer, '100000');
|
|
135
|
+
const tx = decodeTransaction(result);
|
|
136
|
+
expect(tx.LimitAmount).toHaveProperty('currency', currency);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// ==================== OFFER TRANSACTIONS ====================
|
|
142
|
+
describe('buildOfferCreate', () => {
|
|
143
|
+
it('should build OfferCreate with XRP amounts', async () => {
|
|
144
|
+
const takerPays = '1000000';
|
|
145
|
+
const takerGets = '500000';
|
|
146
|
+
|
|
147
|
+
const result = await service.buildOfferCreate(mockAccount, takerPays, takerGets);
|
|
148
|
+
|
|
149
|
+
const tx = decodeTransaction(result);
|
|
150
|
+
expect(tx.TransactionType).toBe('OfferCreate');
|
|
151
|
+
expect(tx.Account).toBe(mockAccount);
|
|
152
|
+
expect(tx.TakerPays).toBe(takerPays);
|
|
153
|
+
expect(tx.TakerGets).toBe(takerGets);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should build OfferCreate with token amounts', async () => {
|
|
157
|
+
const takerPays = { currency: 'USD', issuer: mockIssuer, value: '100' };
|
|
158
|
+
const takerGets = { currency: 'EUR', issuer: mockIssuer, value: '85' };
|
|
159
|
+
|
|
160
|
+
const result = await service.buildOfferCreate(mockAccount, takerPays, takerGets);
|
|
161
|
+
|
|
162
|
+
const tx = decodeTransaction(result);
|
|
163
|
+
expect(tx.TakerPays).toEqual(takerPays);
|
|
164
|
+
expect(tx.TakerGets).toEqual(takerGets);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should build OfferCreate with mixed XRP/token amounts', async () => {
|
|
168
|
+
const takerPays = '1000000'; // XRP
|
|
169
|
+
const takerGets = { currency: 'USD', issuer: mockIssuer, value: '100' };
|
|
170
|
+
|
|
171
|
+
const result = await service.buildOfferCreate(mockAccount, takerPays, takerGets);
|
|
172
|
+
|
|
173
|
+
const tx = decodeTransaction(result);
|
|
174
|
+
expect(tx.TakerPays).toBe(takerPays);
|
|
175
|
+
expect(tx.TakerGets).toEqual(takerGets);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('buildOfferCancel', () => {
|
|
180
|
+
it('should build OfferCancel transaction', async () => {
|
|
181
|
+
const offerSequence = 12345;
|
|
182
|
+
|
|
183
|
+
const result = await service.buildOfferCancel(mockAccount, offerSequence);
|
|
184
|
+
|
|
185
|
+
const tx = decodeTransaction(result);
|
|
186
|
+
expect(tx.TransactionType).toBe('OfferCancel');
|
|
187
|
+
expect(tx.Account).toBe(mockAccount);
|
|
188
|
+
expect(tx.OfferSequence).toBe(offerSequence);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// ==================== ACCOUNTSET TRANSACTIONS ====================
|
|
193
|
+
describe('buildAccountSet', () => {
|
|
194
|
+
it('should build AccountSet with domain', async () => {
|
|
195
|
+
const domain = '6578616D706C652E636F6D'; // example.com in hex
|
|
196
|
+
|
|
197
|
+
const result = await service.buildAccountSet(mockAccount, { domain });
|
|
198
|
+
|
|
199
|
+
const tx = decodeTransaction(result);
|
|
200
|
+
expect(tx.TransactionType).toBe('AccountSet');
|
|
201
|
+
expect(tx.Account).toBe(mockAccount);
|
|
202
|
+
expect(tx.domain).toBe(domain);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should build AccountSet with multiple options', async () => {
|
|
206
|
+
const options = {
|
|
207
|
+
domain: '6578616D706C652E636F6D',
|
|
208
|
+
emailHash: 'abcd1234',
|
|
209
|
+
transferRate: 1005000000,
|
|
210
|
+
tickSize: 5,
|
|
211
|
+
setFlag: 8,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const result = await service.buildAccountSet(mockAccount, options);
|
|
215
|
+
|
|
216
|
+
const tx = decodeTransaction(result);
|
|
217
|
+
expect(tx.domain).toBe(options.domain);
|
|
218
|
+
expect(tx.emailHash).toBe(options.emailHash);
|
|
219
|
+
expect(tx.transferRate).toBe(options.transferRate);
|
|
220
|
+
expect(tx.tickSize).toBe(options.tickSize);
|
|
221
|
+
expect(tx.setFlag).toBe(options.setFlag);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should build AccountSet with clearFlag', async () => {
|
|
225
|
+
const result = await service.buildAccountSet(mockAccount, { clearFlag: 8 });
|
|
226
|
+
|
|
227
|
+
const tx = decodeTransaction(result);
|
|
228
|
+
expect(tx.clearFlag).toBe(8);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should build AccountSet with empty options', async () => {
|
|
232
|
+
const result = await service.buildAccountSet(mockAccount, {});
|
|
233
|
+
|
|
234
|
+
const tx = decodeTransaction(result);
|
|
235
|
+
expect(tx.TransactionType).toBe('AccountSet');
|
|
236
|
+
expect(tx.Account).toBe(mockAccount);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// ==================== ESCROW TRANSACTIONS ====================
|
|
241
|
+
describe('buildEscrowCreate', () => {
|
|
242
|
+
it('should build EscrowCreate without cancelAfter', async () => {
|
|
243
|
+
const amount = '1000000';
|
|
244
|
+
const finishAfter = 1700000000;
|
|
245
|
+
|
|
246
|
+
const result = await service.buildEscrowCreate(
|
|
247
|
+
mockAccount,
|
|
248
|
+
mockDestination,
|
|
249
|
+
amount,
|
|
250
|
+
finishAfter
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
const tx = decodeTransaction(result);
|
|
254
|
+
expect(tx.TransactionType).toBe('EscrowCreate');
|
|
255
|
+
expect(tx.Account).toBe(mockAccount);
|
|
256
|
+
expect(tx.Destination).toBe(mockDestination);
|
|
257
|
+
expect(tx.Amount).toBe(amount);
|
|
258
|
+
expect(tx.FinishAfter).toBe(finishAfter);
|
|
259
|
+
expect(tx.CancelAfter).toBeUndefined();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should build EscrowCreate with cancelAfter', async () => {
|
|
263
|
+
const amount = '1000000';
|
|
264
|
+
const finishAfter = 1700000000;
|
|
265
|
+
const cancelAfter = 1800000000;
|
|
266
|
+
|
|
267
|
+
const result = await service.buildEscrowCreate(
|
|
268
|
+
mockAccount,
|
|
269
|
+
mockDestination,
|
|
270
|
+
amount,
|
|
271
|
+
finishAfter,
|
|
272
|
+
cancelAfter
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const tx = decodeTransaction(result);
|
|
276
|
+
expect(tx.FinishAfter).toBe(finishAfter);
|
|
277
|
+
expect(tx.CancelAfter).toBe(cancelAfter);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
describe('buildEscrowFinish', () => {
|
|
282
|
+
it('should build EscrowFinish transaction', async () => {
|
|
283
|
+
const owner = 'rOwnerAccountXXXXXXXXXXXXXXX';
|
|
284
|
+
const offerSequence = 54321;
|
|
285
|
+
|
|
286
|
+
const result = await service.buildEscrowFinish(mockAccount, owner, offerSequence);
|
|
287
|
+
|
|
288
|
+
const tx = decodeTransaction(result);
|
|
289
|
+
expect(tx.TransactionType).toBe('EscrowFinish');
|
|
290
|
+
expect(tx.Account).toBe(mockAccount);
|
|
291
|
+
expect(tx.Owner).toBe(owner);
|
|
292
|
+
expect(tx.OfferSequence).toBe(offerSequence);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
describe('buildEscrowCancel', () => {
|
|
297
|
+
it('should build EscrowCancel transaction', async () => {
|
|
298
|
+
const owner = 'rOwnerAccountXXXXXXXXXXXXXXX';
|
|
299
|
+
const offerSequence = 54321;
|
|
300
|
+
|
|
301
|
+
const result = await service.buildEscrowCancel(mockAccount, owner, offerSequence);
|
|
302
|
+
|
|
303
|
+
const tx = decodeTransaction(result);
|
|
304
|
+
expect(tx.TransactionType).toBe('EscrowCancel');
|
|
305
|
+
expect(tx.Account).toBe(mockAccount);
|
|
306
|
+
expect(tx.Owner).toBe(owner);
|
|
307
|
+
expect(tx.OfferSequence).toBe(offerSequence);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// ==================== PAYMENT CHANNEL TRANSACTIONS ====================
|
|
312
|
+
describe('buildPaymentChannelCreate', () => {
|
|
313
|
+
it('should build PaymentChannelCreate transaction', async () => {
|
|
314
|
+
const amount = '10000000';
|
|
315
|
+
const settleDelay = 86400;
|
|
316
|
+
const publicKey = '03abcdef1234567890';
|
|
317
|
+
|
|
318
|
+
const result = await service.buildPaymentChannelCreate(
|
|
319
|
+
mockAccount,
|
|
320
|
+
mockDestination,
|
|
321
|
+
amount,
|
|
322
|
+
settleDelay,
|
|
323
|
+
publicKey
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
const tx = decodeTransaction(result);
|
|
327
|
+
expect(tx.TransactionType).toBe('PaymentChannelCreate');
|
|
328
|
+
expect(tx.Account).toBe(mockAccount);
|
|
329
|
+
expect(tx.Destination).toBe(mockDestination);
|
|
330
|
+
expect(tx.Amount).toBe(amount);
|
|
331
|
+
expect(tx.SettleDelay).toBe(settleDelay);
|
|
332
|
+
expect(tx.PublicKey).toBe(publicKey);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
describe('buildPaymentChannelFund', () => {
|
|
337
|
+
it('should build PaymentChannelFund transaction', async () => {
|
|
338
|
+
const channel = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
339
|
+
const amount = '5000000';
|
|
340
|
+
|
|
341
|
+
const result = await service.buildPaymentChannelFund(mockAccount, channel, amount);
|
|
342
|
+
|
|
343
|
+
const tx = decodeTransaction(result);
|
|
344
|
+
expect(tx.TransactionType).toBe('PaymentChannelFund');
|
|
345
|
+
expect(tx.Account).toBe(mockAccount);
|
|
346
|
+
expect(tx.Channel).toBe(channel);
|
|
347
|
+
expect(tx.Amount).toBe(amount);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
describe('buildPaymentChannelClaim', () => {
|
|
352
|
+
it('should build PaymentChannelClaim with amount', async () => {
|
|
353
|
+
const channel = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
354
|
+
const amount = '1000000';
|
|
355
|
+
|
|
356
|
+
const result = await service.buildPaymentChannelClaim(mockAccount, channel, amount);
|
|
357
|
+
|
|
358
|
+
const tx = decodeTransaction(result);
|
|
359
|
+
expect(tx.TransactionType).toBe('PaymentChannelClaim');
|
|
360
|
+
expect(tx.Account).toBe(mockAccount);
|
|
361
|
+
expect(tx.Channel).toBe(channel);
|
|
362
|
+
expect(tx.Amount).toBe(amount);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should build PaymentChannelClaim without amount', async () => {
|
|
366
|
+
const channel = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
367
|
+
|
|
368
|
+
const result = await service.buildPaymentChannelClaim(mockAccount, channel);
|
|
369
|
+
|
|
370
|
+
const tx = decodeTransaction(result);
|
|
371
|
+
expect(tx.TransactionType).toBe('PaymentChannelClaim');
|
|
372
|
+
expect(tx.Channel).toBe(channel);
|
|
373
|
+
expect(tx.Amount).toBeUndefined();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// ==================== CHECK TRANSACTIONS ====================
|
|
378
|
+
describe('buildCheckCreate', () => {
|
|
379
|
+
it('should build CheckCreate transaction', async () => {
|
|
380
|
+
const sendMax = '5000000';
|
|
381
|
+
|
|
382
|
+
const result = await service.buildCheckCreate(mockAccount, mockDestination, sendMax);
|
|
383
|
+
|
|
384
|
+
const tx = decodeTransaction(result);
|
|
385
|
+
expect(tx.TransactionType).toBe('CheckCreate');
|
|
386
|
+
expect(tx.Account).toBe(mockAccount);
|
|
387
|
+
expect(tx.Destination).toBe(mockDestination);
|
|
388
|
+
expect(tx.SendMax).toBe(sendMax);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
describe('buildCheckCash', () => {
|
|
393
|
+
it('should build CheckCash with amount', async () => {
|
|
394
|
+
const checkID = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
395
|
+
const amount = '4000000';
|
|
396
|
+
|
|
397
|
+
const result = await service.buildCheckCash(mockAccount, checkID, amount);
|
|
398
|
+
|
|
399
|
+
const tx = decodeTransaction(result);
|
|
400
|
+
expect(tx.TransactionType).toBe('CheckCash');
|
|
401
|
+
expect(tx.Account).toBe(mockAccount);
|
|
402
|
+
expect(tx.CheckID).toBe(checkID);
|
|
403
|
+
expect(tx.Amount).toBe(amount);
|
|
404
|
+
expect(tx.DeliverMin).toBeUndefined();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('should build CheckCash with deliverMin', async () => {
|
|
408
|
+
const checkID = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
409
|
+
const deliverMin = '3500000';
|
|
410
|
+
|
|
411
|
+
const result = await service.buildCheckCash(mockAccount, checkID, undefined, deliverMin);
|
|
412
|
+
|
|
413
|
+
const tx = decodeTransaction(result);
|
|
414
|
+
expect(tx.Amount).toBeUndefined();
|
|
415
|
+
expect(tx.DeliverMin).toBe(deliverMin);
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('should build CheckCash with both amount and deliverMin', async () => {
|
|
419
|
+
const checkID = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
420
|
+
const amount = '4000000';
|
|
421
|
+
const deliverMin = '3500000';
|
|
422
|
+
|
|
423
|
+
const result = await service.buildCheckCash(mockAccount, checkID, amount, deliverMin);
|
|
424
|
+
|
|
425
|
+
const tx = decodeTransaction(result);
|
|
426
|
+
expect(tx.Amount).toBe(amount);
|
|
427
|
+
expect(tx.DeliverMin).toBe(deliverMin);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('should build CheckCash with neither amount nor deliverMin', async () => {
|
|
431
|
+
const checkID = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
432
|
+
|
|
433
|
+
const result = await service.buildCheckCash(mockAccount, checkID);
|
|
434
|
+
|
|
435
|
+
const tx = decodeTransaction(result);
|
|
436
|
+
expect(tx.CheckID).toBe(checkID);
|
|
437
|
+
expect(tx.Amount).toBeUndefined();
|
|
438
|
+
expect(tx.DeliverMin).toBeUndefined();
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
describe('buildCheckCancel', () => {
|
|
443
|
+
it('should build CheckCancel transaction', async () => {
|
|
444
|
+
const checkID = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
445
|
+
|
|
446
|
+
const result = await service.buildCheckCancel(mockAccount, checkID);
|
|
447
|
+
|
|
448
|
+
const tx = decodeTransaction(result);
|
|
449
|
+
expect(tx.TransactionType).toBe('CheckCancel');
|
|
450
|
+
expect(tx.Account).toBe(mockAccount);
|
|
451
|
+
expect(tx.CheckID).toBe(checkID);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// ==================== DEPOSITPREAUTH TRANSACTIONS ====================
|
|
456
|
+
describe('buildDepositPreauth', () => {
|
|
457
|
+
it('should build DepositPreauth with authorize', async () => {
|
|
458
|
+
const authorize = 'rAuthorizeAccountXXXXXXXXXXX';
|
|
459
|
+
|
|
460
|
+
const result = await service.buildDepositPreauth(mockAccount, authorize);
|
|
461
|
+
|
|
462
|
+
const tx = decodeTransaction(result);
|
|
463
|
+
expect(tx.TransactionType).toBe('DepositPreauth');
|
|
464
|
+
expect(tx.Account).toBe(mockAccount);
|
|
465
|
+
expect(tx.Authorize).toBe(authorize);
|
|
466
|
+
expect(tx.Unauthorize).toBeUndefined();
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
it('should build DepositPreauth with unauthorize', async () => {
|
|
470
|
+
const unauthorize = 'rUnauthorizeAccountXXXXXXXXX';
|
|
471
|
+
|
|
472
|
+
const result = await service.buildDepositPreauth(mockAccount, undefined, unauthorize);
|
|
473
|
+
|
|
474
|
+
const tx = decodeTransaction(result);
|
|
475
|
+
expect(tx.Authorize).toBeUndefined();
|
|
476
|
+
expect(tx.Unauthorize).toBe(unauthorize);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('should build DepositPreauth with neither authorize nor unauthorize', async () => {
|
|
480
|
+
const result = await service.buildDepositPreauth(mockAccount);
|
|
481
|
+
|
|
482
|
+
const tx = decodeTransaction(result);
|
|
483
|
+
expect(tx.TransactionType).toBe('DepositPreauth');
|
|
484
|
+
expect(tx.Account).toBe(mockAccount);
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// ==================== SIGNERLISTSET TRANSACTIONS ====================
|
|
489
|
+
describe('buildSignerListSet', () => {
|
|
490
|
+
it('should build SignerListSet transaction', async () => {
|
|
491
|
+
const signerQuorum = 2;
|
|
492
|
+
const signerEntries = [
|
|
493
|
+
{ account: 'rSigner1XXXXXXXXXXXXXXXXXX', weight: 1 },
|
|
494
|
+
{ account: 'rSigner2XXXXXXXXXXXXXXXXXX', weight: 1 },
|
|
495
|
+
{ account: 'rSigner3XXXXXXXXXXXXXXXXXX', weight: 1 },
|
|
496
|
+
];
|
|
497
|
+
|
|
498
|
+
const result = await service.buildSignerListSet(mockAccount, signerQuorum, signerEntries);
|
|
499
|
+
|
|
500
|
+
const tx = decodeTransaction(result);
|
|
501
|
+
expect(tx.TransactionType).toBe('SignerListSet');
|
|
502
|
+
expect(tx.Account).toBe(mockAccount);
|
|
503
|
+
expect(tx.SignerQuorum).toBe(signerQuorum);
|
|
504
|
+
expect(tx.SignerEntries).toEqual([
|
|
505
|
+
{ SignerEntry: { Account: 'rSigner1XXXXXXXXXXXXXXXXXX', SignerWeight: 1 } },
|
|
506
|
+
{ SignerEntry: { Account: 'rSigner2XXXXXXXXXXXXXXXXXX', SignerWeight: 1 } },
|
|
507
|
+
{ SignerEntry: { Account: 'rSigner3XXXXXXXXXXXXXXXXXX', SignerWeight: 1 } },
|
|
508
|
+
]);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it('should build SignerListSet with different weights', async () => {
|
|
512
|
+
const signerQuorum = 3;
|
|
513
|
+
const signerEntries = [
|
|
514
|
+
{ account: 'rSigner1XXXXXXXXXXXXXXXXXX', weight: 2 },
|
|
515
|
+
{ account: 'rSigner2XXXXXXXXXXXXXXXXXX', weight: 1 },
|
|
516
|
+
];
|
|
517
|
+
|
|
518
|
+
const result = await service.buildSignerListSet(mockAccount, signerQuorum, signerEntries);
|
|
519
|
+
|
|
520
|
+
const tx = decodeTransaction(result);
|
|
521
|
+
expect(tx.SignerQuorum).toBe(3);
|
|
522
|
+
expect(tx.SignerEntries).toHaveLength(2);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
it('should build SignerListSet with empty signer list (disable multisig)', async () => {
|
|
526
|
+
const result = await service.buildSignerListSet(mockAccount, 0, []);
|
|
527
|
+
|
|
528
|
+
const tx = decodeTransaction(result);
|
|
529
|
+
expect(tx.SignerQuorum).toBe(0);
|
|
530
|
+
expect(tx.SignerEntries).toEqual([]);
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// ==================== TICKETCREATE TRANSACTIONS ====================
|
|
535
|
+
describe('buildTicketCreate', () => {
|
|
536
|
+
it('should build TicketCreate transaction', async () => {
|
|
537
|
+
const ticketCount = 10;
|
|
538
|
+
|
|
539
|
+
const result = await service.buildTicketCreate(mockAccount, ticketCount);
|
|
540
|
+
|
|
541
|
+
const tx = decodeTransaction(result);
|
|
542
|
+
expect(tx.TransactionType).toBe('TicketCreate');
|
|
543
|
+
expect(tx.Account).toBe(mockAccount);
|
|
544
|
+
expect(tx.TicketCount).toBe(ticketCount);
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
it('should build TicketCreate with minimum ticket count', async () => {
|
|
548
|
+
const result = await service.buildTicketCreate(mockAccount, 1);
|
|
549
|
+
|
|
550
|
+
const tx = decodeTransaction(result);
|
|
551
|
+
expect(tx.TicketCount).toBe(1);
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it('should build TicketCreate with maximum ticket count', async () => {
|
|
555
|
+
const result = await service.buildTicketCreate(mockAccount, 250);
|
|
556
|
+
|
|
557
|
+
const tx = decodeTransaction(result);
|
|
558
|
+
expect(tx.TicketCount).toBe(250);
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
// ==================== NFT TRANSACTIONS ====================
|
|
563
|
+
describe('buildNFTMint', () => {
|
|
564
|
+
it('should build NFTokenMint transaction', async () => {
|
|
565
|
+
const uri = '697066733A2F2F6261666B7265696768'; // ipfs://... in hex
|
|
566
|
+
const flags = 8; // tfTransferable
|
|
567
|
+
const transferFee = 500; // 5% in basis points
|
|
568
|
+
const taxon = 0;
|
|
569
|
+
|
|
570
|
+
const result = await service.buildNFTMint(mockAccount, uri, flags, transferFee, taxon);
|
|
571
|
+
|
|
572
|
+
const tx = decodeTransaction(result);
|
|
573
|
+
expect(tx.TransactionType).toBe('NFTokenMint');
|
|
574
|
+
expect(tx.Account).toBe(mockAccount);
|
|
575
|
+
expect(tx.URI).toBe(uri);
|
|
576
|
+
expect(tx.Flags).toBe(flags);
|
|
577
|
+
expect(tx.TransferFee).toBe(transferFee);
|
|
578
|
+
expect(tx.NFTokenTaxon).toBe(taxon);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it('should build NFTokenMint with different taxons', async () => {
|
|
582
|
+
const taxons = [0, 1, 100, 999999];
|
|
583
|
+
|
|
584
|
+
for (const taxon of taxons) {
|
|
585
|
+
const result = await service.buildNFTMint(mockAccount, 'abc', 0, 0, taxon);
|
|
586
|
+
const tx = decodeTransaction(result);
|
|
587
|
+
expect(tx.NFTokenTaxon).toBe(taxon);
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
describe('buildNFTBurn', () => {
|
|
593
|
+
it('should build NFTokenBurn transaction', async () => {
|
|
594
|
+
const nftokenID = '000800006203F49C21D5D6E022CB16DE3538F248662FC73C00000000000001E2';
|
|
595
|
+
|
|
596
|
+
const result = await service.buildNFTBurn(mockAccount, nftokenID);
|
|
597
|
+
|
|
598
|
+
const tx = decodeTransaction(result);
|
|
599
|
+
expect(tx.TransactionType).toBe('NFTokenBurn');
|
|
600
|
+
expect(tx.Account).toBe(mockAccount);
|
|
601
|
+
expect(tx.NFTokenID).toBe(nftokenID);
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
describe('buildNFTCreateOffer', () => {
|
|
606
|
+
it('should build NFTokenCreateOffer for sell', async () => {
|
|
607
|
+
const nftokenID = '000800006203F49C21D5D6E022CB16DE3538F248662FC73C00000000000001E2';
|
|
608
|
+
const amount = '1000000';
|
|
609
|
+
const flags = 1; // tfSellNFToken
|
|
610
|
+
|
|
611
|
+
const result = await service.buildNFTCreateOffer(mockAccount, nftokenID, amount, flags);
|
|
612
|
+
|
|
613
|
+
const tx = decodeTransaction(result);
|
|
614
|
+
expect(tx.TransactionType).toBe('NFTokenCreateOffer');
|
|
615
|
+
expect(tx.Account).toBe(mockAccount);
|
|
616
|
+
expect(tx.NFTokenID).toBe(nftokenID);
|
|
617
|
+
expect(tx.Amount).toBe(amount);
|
|
618
|
+
expect(tx.Flags).toBe(flags);
|
|
619
|
+
expect(tx.Destination).toBeUndefined();
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('should build NFTokenCreateOffer for buy', async () => {
|
|
623
|
+
const nftokenID = '000800006203F49C21D5D6E022CB16DE3538F248662FC73C00000000000001E2';
|
|
624
|
+
const amount = '500000';
|
|
625
|
+
const flags = 0; // Buy offer
|
|
626
|
+
|
|
627
|
+
const result = await service.buildNFTCreateOffer(mockAccount, nftokenID, amount, flags);
|
|
628
|
+
|
|
629
|
+
const tx = decodeTransaction(result);
|
|
630
|
+
expect(tx.Flags).toBe(0);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
it('should build NFTokenCreateOffer with destination', async () => {
|
|
634
|
+
const nftokenID = '000800006203F49C21D5D6E022CB16DE3538F248662FC73C00000000000001E2';
|
|
635
|
+
const amount = '1000000';
|
|
636
|
+
const flags = 1;
|
|
637
|
+
|
|
638
|
+
const result = await service.buildNFTCreateOffer(
|
|
639
|
+
mockAccount,
|
|
640
|
+
nftokenID,
|
|
641
|
+
amount,
|
|
642
|
+
flags,
|
|
643
|
+
mockDestination
|
|
644
|
+
);
|
|
645
|
+
|
|
646
|
+
const tx = decodeTransaction(result);
|
|
647
|
+
expect(tx.Destination).toBe(mockDestination);
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
describe('buildNFTAcceptOffer', () => {
|
|
652
|
+
it('should build NFTokenAcceptOffer with sell offer', async () => {
|
|
653
|
+
const sellOffer = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
654
|
+
|
|
655
|
+
const result = await service.buildNFTAcceptOffer(mockAccount, sellOffer);
|
|
656
|
+
|
|
657
|
+
const tx = decodeTransaction(result);
|
|
658
|
+
expect(tx.TransactionType).toBe('NFTokenAcceptOffer');
|
|
659
|
+
expect(tx.Account).toBe(mockAccount);
|
|
660
|
+
expect(tx.NFTokenSellOffer).toBe(sellOffer);
|
|
661
|
+
expect(tx.NFTokenBuyOffer).toBeUndefined();
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
it('should build NFTokenAcceptOffer with buy offer', async () => {
|
|
665
|
+
const buyOffer = 'D2BF7EEEFC16CF3089D1BAE7FF413059E0644802EC859EDEE4C96A03089D1BAE';
|
|
666
|
+
|
|
667
|
+
const result = await service.buildNFTAcceptOffer(mockAccount, undefined, buyOffer);
|
|
668
|
+
|
|
669
|
+
const tx = decodeTransaction(result);
|
|
670
|
+
expect(tx.NFTokenSellOffer).toBeUndefined();
|
|
671
|
+
expect(tx.NFTokenBuyOffer).toBe(buyOffer);
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
it('should build NFTokenAcceptOffer with both offers (brokered mode)', async () => {
|
|
675
|
+
const sellOffer = 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA';
|
|
676
|
+
const buyOffer = 'D2BF7EEEFC16CF3089D1BAE7FF413059E0644802EC859EDEE4C96A03089D1BAE';
|
|
677
|
+
|
|
678
|
+
const result = await service.buildNFTAcceptOffer(mockAccount, sellOffer, buyOffer);
|
|
679
|
+
|
|
680
|
+
const tx = decodeTransaction(result);
|
|
681
|
+
expect(tx.NFTokenSellOffer).toBe(sellOffer);
|
|
682
|
+
expect(tx.NFTokenBuyOffer).toBe(buyOffer);
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
describe('buildNFTCancelOffer', () => {
|
|
687
|
+
it('should build NFTokenCancelOffer with single offer', async () => {
|
|
688
|
+
const offers = ['C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA'];
|
|
689
|
+
|
|
690
|
+
const result = await service.buildNFTCancelOffer(mockAccount, offers);
|
|
691
|
+
|
|
692
|
+
const tx = decodeTransaction(result);
|
|
693
|
+
expect(tx.TransactionType).toBe('NFTokenCancelOffer');
|
|
694
|
+
expect(tx.Account).toBe(mockAccount);
|
|
695
|
+
expect(tx.NFTokenOffers).toEqual(offers);
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
it('should build NFTokenCancelOffer with multiple offers', async () => {
|
|
699
|
+
const offers = [
|
|
700
|
+
'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B95992978C0BA',
|
|
701
|
+
'D2BF7EEEFC16CF3089D1BAE7FF413059E0644802EC859EDEE4C96A03089D1BAE',
|
|
702
|
+
'E3CG8FFFGD27DG4190E2CBF8GG524160F1755913FD960FEEF5D97B14190E2CBF',
|
|
703
|
+
];
|
|
704
|
+
|
|
705
|
+
const result = await service.buildNFTCancelOffer(mockAccount, offers);
|
|
706
|
+
|
|
707
|
+
const tx = decodeTransaction(result);
|
|
708
|
+
expect(tx.NFTokenOffers).toHaveLength(3);
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
// ==================== BATCH TRANSACTIONS ====================
|
|
713
|
+
describe('buildBatchTransaction', () => {
|
|
714
|
+
const tfAllOrNothing = 65536;
|
|
715
|
+
const tfInnerBatchTxn = 1073741824;
|
|
716
|
+
|
|
717
|
+
it('should build batch with payment transactions', async () => {
|
|
718
|
+
const innerTransactions = [
|
|
719
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '1000000' },
|
|
720
|
+
{ type: 'payment' as const, destination: 'rAnotherAccount', amount: '2000000' },
|
|
721
|
+
];
|
|
722
|
+
|
|
723
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
724
|
+
|
|
725
|
+
const tx = decodeTransaction(result);
|
|
726
|
+
expect(tx.TransactionType).toBe('Batch');
|
|
727
|
+
expect(tx.Account).toBe(mockAccount);
|
|
728
|
+
expect(tx.Flags).toBe(tfAllOrNothing);
|
|
729
|
+
expect(tx.RawTransactions).toHaveLength(2);
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
it('should build batch with trust-set transactions', async () => {
|
|
733
|
+
const innerTransactions = [
|
|
734
|
+
{ type: 'trust-set' as const, currency: 'USD', issuer: mockIssuer, amount: '1000000' },
|
|
735
|
+
];
|
|
736
|
+
|
|
737
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
738
|
+
|
|
739
|
+
const tx = decodeTransaction(result);
|
|
740
|
+
const rawTx = (tx.RawTransactions as Array<{ RawTransaction: Record<string, unknown> }>)[0];
|
|
741
|
+
expect(rawTx.RawTransaction.TransactionType).toBe('TrustSet');
|
|
742
|
+
expect(rawTx.RawTransaction.Flags).toBe(tfInnerBatchTxn);
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
it('should build batch with nft-mint transactions', async () => {
|
|
746
|
+
const innerTransactions = [{ type: 'nft-mint' as const }];
|
|
747
|
+
|
|
748
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
749
|
+
|
|
750
|
+
const tx = decodeTransaction(result);
|
|
751
|
+
const rawTx = (tx.RawTransactions as Array<{ RawTransaction: Record<string, unknown> }>)[0];
|
|
752
|
+
expect(rawTx.RawTransaction.TransactionType).toBe('NFTokenMint');
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
it('should build batch with token payment', async () => {
|
|
756
|
+
const innerTransactions = [
|
|
757
|
+
{
|
|
758
|
+
type: 'payment' as const,
|
|
759
|
+
destination: mockDestination,
|
|
760
|
+
amount: '100',
|
|
761
|
+
currency: 'USD',
|
|
762
|
+
issuer: mockIssuer,
|
|
763
|
+
},
|
|
764
|
+
];
|
|
765
|
+
|
|
766
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
767
|
+
|
|
768
|
+
const tx = decodeTransaction(result);
|
|
769
|
+
const rawTx = (tx.RawTransactions as Array<{ RawTransaction: Record<string, unknown> }>)[0];
|
|
770
|
+
expect(rawTx.RawTransaction.Amount).toEqual({
|
|
771
|
+
currency: 'USD',
|
|
772
|
+
issuer: mockIssuer,
|
|
773
|
+
value: '100',
|
|
774
|
+
});
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it('should build batch with default payment for unknown type', async () => {
|
|
778
|
+
const innerTransactions = [{ type: 'unknown' as any }];
|
|
779
|
+
|
|
780
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
781
|
+
|
|
782
|
+
const tx = decodeTransaction(result);
|
|
783
|
+
const rawTx = (tx.RawTransactions as Array<{ RawTransaction: Record<string, unknown> }>)[0];
|
|
784
|
+
expect(rawTx.RawTransaction.TransactionType).toBe('Payment');
|
|
785
|
+
expect(rawTx.RawTransaction.Amount).toBe('1');
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
it('should set correct sequence numbers for inner transactions', async () => {
|
|
789
|
+
const innerTransactions = [
|
|
790
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '1000000' },
|
|
791
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '2000000' },
|
|
792
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '3000000' },
|
|
793
|
+
];
|
|
794
|
+
|
|
795
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
796
|
+
|
|
797
|
+
const tx = decodeTransaction(result);
|
|
798
|
+
const rawTxs = tx.RawTransactions as Array<{ RawTransaction: Record<string, unknown> }>;
|
|
799
|
+
expect(rawTxs[0].RawTransaction.Sequence).toBe(1);
|
|
800
|
+
expect(rawTxs[1].RawTransaction.Sequence).toBe(2);
|
|
801
|
+
expect(rawTxs[2].RawTransaction.Sequence).toBe(3);
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
it('should set Fee to 0 and empty SigningPubKey for inner transactions', async () => {
|
|
805
|
+
const innerTransactions = [
|
|
806
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '1000000' },
|
|
807
|
+
];
|
|
808
|
+
|
|
809
|
+
const result = await service.buildBatchTransaction(mockAccount, innerTransactions);
|
|
810
|
+
|
|
811
|
+
const tx = decodeTransaction(result);
|
|
812
|
+
const rawTx = (tx.RawTransactions as Array<{ RawTransaction: Record<string, unknown> }>)[0];
|
|
813
|
+
expect(rawTx.RawTransaction.Fee).toBe('0');
|
|
814
|
+
expect(rawTx.RawTransaction.SigningPubKey).toBe('');
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
describe('buildBatchInnerTransactions', () => {
|
|
819
|
+
it('should build inner transactions with payment (XRP)', async () => {
|
|
820
|
+
const innerTransactions = [
|
|
821
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '1000000' },
|
|
822
|
+
];
|
|
823
|
+
|
|
824
|
+
const result = await service.buildBatchInnerTransactions(mockAccount, innerTransactions);
|
|
825
|
+
|
|
826
|
+
expect(result).toHaveLength(1);
|
|
827
|
+
expect(result[0].payload).toBeDefined();
|
|
828
|
+
expect(result[0].description).toContain('Send');
|
|
829
|
+
expect(result[0].description).toContain('XRP');
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
it('should build inner transactions with payment (token)', async () => {
|
|
833
|
+
const innerTransactions = [
|
|
834
|
+
{
|
|
835
|
+
type: 'payment' as const,
|
|
836
|
+
destination: mockDestination,
|
|
837
|
+
amount: '100',
|
|
838
|
+
currency: 'USD',
|
|
839
|
+
issuer: mockIssuer,
|
|
840
|
+
},
|
|
841
|
+
];
|
|
842
|
+
|
|
843
|
+
const result = await service.buildBatchInnerTransactions(mockAccount, innerTransactions);
|
|
844
|
+
|
|
845
|
+
expect(result[0].description).toContain('100 USD');
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
it('should build inner transactions with trust-set', async () => {
|
|
849
|
+
const innerTransactions = [
|
|
850
|
+
{ type: 'trust-set' as const, currency: 'EUR', issuer: mockIssuer, amount: '500000' },
|
|
851
|
+
];
|
|
852
|
+
|
|
853
|
+
const result = await service.buildBatchInnerTransactions(mockAccount, innerTransactions);
|
|
854
|
+
|
|
855
|
+
expect(result[0].description).toContain('trust line');
|
|
856
|
+
expect(result[0].description).toContain('EUR');
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
it('should build inner transactions with nft-mint', async () => {
|
|
860
|
+
const innerTransactions = [
|
|
861
|
+
{ type: 'nft-mint' as const, uri: '697066733A2F2F', taxon: 42 },
|
|
862
|
+
];
|
|
863
|
+
|
|
864
|
+
const result = await service.buildBatchInnerTransactions(mockAccount, innerTransactions);
|
|
865
|
+
|
|
866
|
+
expect(result[0].description).toContain('Mint NFT');
|
|
867
|
+
expect(result[0].description).toContain('42');
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
it('should throw error for unknown transaction type', async () => {
|
|
871
|
+
const innerTransactions = [{ type: 'invalid-type' as any }];
|
|
872
|
+
|
|
873
|
+
await expect(
|
|
874
|
+
service.buildBatchInnerTransactions(mockAccount, innerTransactions)
|
|
875
|
+
).rejects.toThrow('Unknown transaction type');
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
it('should return base64 encoded payloads', async () => {
|
|
879
|
+
const innerTransactions = [
|
|
880
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '1000000' },
|
|
881
|
+
];
|
|
882
|
+
|
|
883
|
+
const result = await service.buildBatchInnerTransactions(mockAccount, innerTransactions);
|
|
884
|
+
|
|
885
|
+
// Verify it's valid base64
|
|
886
|
+
expect(() => atob(result[0].payload)).not.toThrow();
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
it('should build multiple inner transactions', async () => {
|
|
890
|
+
const innerTransactions = [
|
|
891
|
+
{ type: 'payment' as const, destination: mockDestination, amount: '1000000' },
|
|
892
|
+
{ type: 'trust-set' as const, currency: 'USD', issuer: mockIssuer },
|
|
893
|
+
{ type: 'nft-mint' as const, taxon: 0 },
|
|
894
|
+
];
|
|
895
|
+
|
|
896
|
+
const result = await service.buildBatchInnerTransactions(mockAccount, innerTransactions);
|
|
897
|
+
|
|
898
|
+
expect(result).toHaveLength(3);
|
|
899
|
+
expect(result[0].description).toContain('XRP');
|
|
900
|
+
expect(result[1].description).toContain('trust line');
|
|
901
|
+
expect(result[2].description).toContain('NFT');
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
// ==================== SERIALIZATION ====================
|
|
906
|
+
describe('serializeTransaction', () => {
|
|
907
|
+
it('should produce valid base64 output', async () => {
|
|
908
|
+
const result = await service.buildPayment(mockAccount, mockDestination, '1000000');
|
|
909
|
+
|
|
910
|
+
// Should be valid base64
|
|
911
|
+
expect(() => atob(result)).not.toThrow();
|
|
912
|
+
|
|
913
|
+
// Should produce valid JSON when decoded
|
|
914
|
+
const decoded = atob(result);
|
|
915
|
+
expect(() => JSON.parse(decoded)).not.toThrow();
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
it('should preserve all transaction fields', async () => {
|
|
919
|
+
const result = await service.buildPayment(
|
|
920
|
+
mockAccount,
|
|
921
|
+
mockDestination,
|
|
922
|
+
'100',
|
|
923
|
+
true,
|
|
924
|
+
'USD',
|
|
925
|
+
mockIssuer
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
const tx = decodeTransaction(result);
|
|
929
|
+
|
|
930
|
+
// Verify all expected fields are present
|
|
931
|
+
expect(tx).toHaveProperty('TransactionType');
|
|
932
|
+
expect(tx).toHaveProperty('Account');
|
|
933
|
+
expect(tx).toHaveProperty('Destination');
|
|
934
|
+
expect(tx).toHaveProperty('Amount');
|
|
935
|
+
});
|
|
936
|
+
});
|
|
937
|
+
});
|