@cardano-sdk/wallet 0.1.4 → 0.1.8
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/LICENSE +201 -0
- package/NOTICE +5 -0
- package/README.md +8 -0
- package/dist/KeyManagement/InMemoryKeyManager.d.ts +9 -0
- package/dist/KeyManagement/InMemoryKeyManager.d.ts.map +1 -0
- package/dist/KeyManagement/InMemoryKeyManager.js +94 -0
- package/dist/KeyManagement/InMemoryKeyManager.js.map +1 -0
- package/dist/KeyManagement/errors/InvalidMnemonic.d.ts +5 -0
- package/dist/KeyManagement/errors/InvalidMnemonic.d.ts.map +1 -0
- package/dist/KeyManagement/errors/InvalidMnemonic.js +13 -0
- package/dist/KeyManagement/errors/InvalidMnemonic.js.map +1 -0
- package/{src/KeyManagement/errors/index.ts → dist/KeyManagement/errors/index.d.ts} +1 -0
- package/dist/KeyManagement/errors/index.d.ts.map +1 -0
- package/dist/KeyManagement/errors/index.js +6 -0
- package/dist/KeyManagement/errors/index.js.map +1 -0
- package/{src/KeyManagement/index.ts → dist/KeyManagement/index.d.ts} +1 -0
- package/dist/KeyManagement/index.d.ts.map +1 -0
- package/dist/KeyManagement/index.js +30 -0
- package/dist/KeyManagement/index.js.map +1 -0
- package/dist/KeyManagement/types.d.ts +30 -0
- package/dist/KeyManagement/types.d.ts.map +1 -0
- package/dist/KeyManagement/types.js +15 -0
- package/dist/KeyManagement/types.js.map +1 -0
- package/dist/KeyManagement/util.d.ts +6 -0
- package/dist/KeyManagement/util.d.ts.map +1 -0
- package/dist/KeyManagement/util.js +31 -0
- package/dist/KeyManagement/util.js.map +1 -0
- package/dist/SingleAddressWallet.d.ts +45 -0
- package/dist/SingleAddressWallet.d.ts.map +1 -0
- package/dist/SingleAddressWallet.js +158 -0
- package/dist/SingleAddressWallet.js.map +1 -0
- package/dist/Transaction/computeImplicitCoin.d.ts +4 -0
- package/dist/Transaction/computeImplicitCoin.d.ts.map +1 -0
- package/dist/Transaction/computeImplicitCoin.js +21 -0
- package/dist/Transaction/computeImplicitCoin.js.map +1 -0
- package/dist/Transaction/createTransactionInternals.d.ts +16 -0
- package/dist/Transaction/createTransactionInternals.d.ts.map +1 -0
- package/dist/Transaction/createTransactionInternals.js +28 -0
- package/dist/Transaction/createTransactionInternals.js.map +1 -0
- package/dist/Transaction/ensureValidityInterval.d.ts +3 -0
- package/dist/Transaction/ensureValidityInterval.d.ts.map +1 -0
- package/dist/Transaction/ensureValidityInterval.js +6 -0
- package/dist/Transaction/ensureValidityInterval.js.map +1 -0
- package/dist/Transaction/index.d.ts +4 -0
- package/dist/Transaction/index.d.ts.map +1 -0
- package/dist/Transaction/index.js +16 -0
- package/dist/Transaction/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/services/AssetsTracker.d.ts +16 -0
- package/dist/services/AssetsTracker.d.ts.map +1 -0
- package/dist/services/AssetsTracker.js +13 -0
- package/dist/services/AssetsTracker.js.map +1 -0
- package/dist/services/BalanceTracker.d.ts +5 -0
- package/dist/services/BalanceTracker.d.ts.map +1 -0
- package/dist/services/BalanceTracker.js +43 -0
- package/dist/services/BalanceTracker.js.map +1 -0
- package/dist/services/DelegationTracker/DelegationTracker.d.ts +26 -0
- package/dist/services/DelegationTracker/DelegationTracker.d.ts.map +1 -0
- package/dist/services/DelegationTracker/DelegationTracker.js +39 -0
- package/dist/services/DelegationTracker/DelegationTracker.js.map +1 -0
- package/dist/services/DelegationTracker/RewardAccounts.d.ts +36 -0
- package/dist/services/DelegationTracker/RewardAccounts.d.ts.map +1 -0
- package/dist/services/DelegationTracker/RewardAccounts.js +86 -0
- package/dist/services/DelegationTracker/RewardAccounts.js.map +1 -0
- package/dist/services/DelegationTracker/RewardsHistory.d.ts +14 -0
- package/dist/services/DelegationTracker/RewardsHistory.d.ts.map +1 -0
- package/dist/services/DelegationTracker/RewardsHistory.js +27 -0
- package/dist/services/DelegationTracker/RewardsHistory.js.map +1 -0
- package/dist/services/DelegationTracker/index.d.ts +5 -0
- package/dist/services/DelegationTracker/index.d.ts.map +1 -0
- package/dist/services/DelegationTracker/index.js +17 -0
- package/dist/services/DelegationTracker/index.js.map +1 -0
- package/dist/services/DelegationTracker/transactionCertificates.d.ts +9 -0
- package/dist/services/DelegationTracker/transactionCertificates.d.ts.map +1 -0
- package/dist/services/DelegationTracker/transactionCertificates.js +33 -0
- package/dist/services/DelegationTracker/transactionCertificates.js.map +1 -0
- package/dist/services/DelegationTracker/types.d.ts +6 -0
- package/dist/services/DelegationTracker/types.d.ts.map +1 -0
- package/dist/services/DelegationTracker/types.js +3 -0
- package/dist/services/DelegationTracker/types.js.map +1 -0
- package/dist/services/TransactionError.d.ts +15 -0
- package/dist/services/TransactionError.d.ts.map +1 -0
- package/dist/services/TransactionError.js +23 -0
- package/dist/services/TransactionError.js.map +1 -0
- package/dist/services/TransactionsTracker.d.ts +22 -0
- package/dist/services/TransactionsTracker.d.ts.map +1 -0
- package/dist/services/TransactionsTracker.js +75 -0
- package/dist/services/TransactionsTracker.js.map +1 -0
- package/dist/services/UtxoTracker.d.ts +18 -0
- package/dist/services/UtxoTracker.d.ts.map +1 -0
- package/dist/services/UtxoTracker.js +20 -0
- package/dist/services/UtxoTracker.js.map +1 -0
- package/dist/services/index.d.ts +9 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +21 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/types.d.ts +81 -0
- package/dist/services/types.d.ts.map +1 -0
- package/dist/services/types.js +16 -0
- package/dist/services/types.js.map +1 -0
- package/dist/services/util/SyncableIntervalTrackerSubject.d.ts +19 -0
- package/dist/services/util/SyncableIntervalTrackerSubject.d.ts.map +1 -0
- package/dist/services/util/SyncableIntervalTrackerSubject.js +30 -0
- package/dist/services/util/SyncableIntervalTrackerSubject.js.map +1 -0
- package/dist/services/util/TrackerSubject.d.ts +14 -0
- package/dist/services/util/TrackerSubject.d.ts.map +1 -0
- package/dist/services/util/TrackerSubject.js +46 -0
- package/dist/services/util/TrackerSubject.js.map +1 -0
- package/dist/services/util/coldObservableProvider.d.ts +4 -0
- package/dist/services/util/coldObservableProvider.d.ts.map +1 -0
- package/dist/services/util/coldObservableProvider.js +14 -0
- package/dist/services/util/coldObservableProvider.js.map +1 -0
- package/dist/services/util/equals.d.ts +9 -0
- package/dist/services/util/equals.d.ts.map +1 -0
- package/dist/services/util/equals.js +19 -0
- package/dist/services/util/equals.js.map +1 -0
- package/dist/services/util/index.d.ts +6 -0
- package/dist/services/util/index.d.ts.map +1 -0
- package/dist/services/util/index.js +18 -0
- package/dist/services/util/index.js.map +1 -0
- package/dist/services/util/trigger.d.ts +5 -0
- package/dist/services/util/trigger.d.ts.map +1 -0
- package/dist/services/util/trigger.js +9 -0
- package/dist/services/util/trigger.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +17 -8
- package/jest.config.js +0 -1
- package/src/Address.ts +0 -12
- package/src/BalanceTracker.ts +0 -62
- package/src/InMemoryTransactionTracker.ts +0 -87
- package/src/InMemoryUtxoRepository.ts +0 -192
- package/src/KeyManagement/InMemoryKeyManager.ts +0 -67
- package/src/KeyManagement/errors/InvalidMnemonic.ts +0 -9
- package/src/KeyManagement/types.ts +0 -15
- package/src/KeyManagement/util.ts +0 -14
- package/src/SingleAddressWallet.ts +0 -120
- package/src/Transaction/CertificateFactory.ts +0 -154
- package/src/Transaction/computeImplicitCoin.ts +0 -36
- package/src/Transaction/createTransactionInternals.ts +0 -60
- package/src/Transaction/index.ts +0 -5
- package/src/Transaction/types.ts +0 -12
- package/src/Transaction/withdrawal.ts +0 -17
- package/src/TransactionError.ts +0 -17
- package/src/index.ts +0 -9
- package/src/tsconfig.json +0 -11
- package/src/types.ts +0 -56
- package/test/.eslintrc.js +0 -7
- package/test/BalanceTracker.test.ts +0 -44
- package/test/InMemoryTransactionTracker.test.ts +0 -108
- package/test/InMemoryUtxoRepository.test.ts +0 -242
- package/test/KeyManagement/InMemoryKeyManager.test.ts +0 -39
- package/test/SingleAddressWallet.test.ts +0 -87
- package/test/Transaction/CertificateFactory.test.ts +0 -89
- package/test/Transaction/computeImplicitCoin.test.ts +0 -26
- package/test/Transaction/createTransactionInternals.test.ts +0 -84
- package/test/Transaction/withdrawal.test.ts +0 -13
- package/test/integration/withdrawal.test.ts +0 -108
- package/test/mocks/MockTransactionTracker.ts +0 -8
- package/test/mocks/MockUtxoRepository.ts +0 -13
- package/test/mocks/ProviderStub.ts +0 -151
- package/test/mocks/index.ts +0 -4
- package/test/mocks/testKeyManager.ts +0 -10
- package/test/tsconfig.json +0 -12
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Cardano, CardanoSerializationLib, CSL, Ogmios } from '@cardano-sdk/core';
|
|
2
|
-
import { KeyManager } from '../KeyManagement';
|
|
3
|
-
|
|
4
|
-
export type Withdrawal = {
|
|
5
|
-
address: CSL.RewardAddress;
|
|
6
|
-
quantity: CSL.BigNum;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const withdrawal = (
|
|
10
|
-
csl: CardanoSerializationLib,
|
|
11
|
-
keyManager: KeyManager,
|
|
12
|
-
quantity: Ogmios.Lovelace,
|
|
13
|
-
network: number = Cardano.NetworkId.mainnet
|
|
14
|
-
): Withdrawal => ({
|
|
15
|
-
address: csl.RewardAddress.new(network, csl.StakeCredential.from_keyhash(keyManager.stakeKey.hash())),
|
|
16
|
-
quantity: csl.BigNum.from_str(quantity.toString())
|
|
17
|
-
});
|
package/src/TransactionError.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { CustomError } from 'ts-custom-error';
|
|
2
|
-
|
|
3
|
-
export enum TransactionFailure {
|
|
4
|
-
InvalidTransaction = 'INVALID_TRANSACTION',
|
|
5
|
-
FailedToSubmit = 'FAILED_TO_SUBMIT',
|
|
6
|
-
Unknown = 'UNKNOWN',
|
|
7
|
-
CannotTrack = 'CANNOT_TRACK',
|
|
8
|
-
Timeout = 'TIMEOUT'
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const formatDetail = (detail?: string) => (detail ? ` (${detail})` : '');
|
|
12
|
-
|
|
13
|
-
export class TransactionError extends CustomError {
|
|
14
|
-
constructor(public reason: TransactionFailure, public innerError?: unknown, public detail?: string) {
|
|
15
|
-
super(`Transaction failed: ${reason}${formatDetail(detail)}`);
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export * as Address from './Address';
|
|
2
|
-
export * as Transaction from './Transaction';
|
|
3
|
-
export * from './InMemoryUtxoRepository';
|
|
4
|
-
export * from './InMemoryTransactionTracker';
|
|
5
|
-
export * as KeyManagement from './KeyManagement';
|
|
6
|
-
export * from './SingleAddressWallet';
|
|
7
|
-
export * from './types';
|
|
8
|
-
export * from './TransactionError';
|
|
9
|
-
export * from './BalanceTracker';
|
package/src/tsconfig.json
DELETED
package/src/types.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import Schema from '@cardano-ogmios/schema';
|
|
2
|
-
import { ImplicitCoin, SelectionConstraints, SelectionResult } from '@cardano-sdk/cip2';
|
|
3
|
-
import { CSL, Ogmios } from '@cardano-sdk/core';
|
|
4
|
-
import Emittery from 'emittery';
|
|
5
|
-
|
|
6
|
-
export enum UtxoRepositoryEvent {
|
|
7
|
-
Changed = 'changed',
|
|
8
|
-
OutOfSync = 'out-of-sync'
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface UtxoRepositoryFields {
|
|
12
|
-
allUtxos: Schema.Utxo;
|
|
13
|
-
availableUtxos: Schema.Utxo;
|
|
14
|
-
allRewards: Ogmios.Lovelace | null;
|
|
15
|
-
availableRewards: Ogmios.Lovelace | null;
|
|
16
|
-
delegation: Schema.PoolId | null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type UtxoRepositoryEvents = {
|
|
20
|
-
changed: UtxoRepositoryFields;
|
|
21
|
-
'out-of-sync': void;
|
|
22
|
-
'transaction-untracked': CSL.Transaction;
|
|
23
|
-
};
|
|
24
|
-
export type UtxoRepository = {
|
|
25
|
-
sync: () => Promise<void>;
|
|
26
|
-
selectInputs: (
|
|
27
|
-
outputs: Set<CSL.TransactionOutput>,
|
|
28
|
-
constraints: SelectionConstraints,
|
|
29
|
-
implicitCoin?: ImplicitCoin
|
|
30
|
-
) => Promise<SelectionResult>;
|
|
31
|
-
} & UtxoRepositoryFields &
|
|
32
|
-
Emittery<UtxoRepositoryEvents>;
|
|
33
|
-
|
|
34
|
-
export interface OnTransactionArgs {
|
|
35
|
-
transaction: CSL.Transaction;
|
|
36
|
-
/**
|
|
37
|
-
* Resolves when transaction is confirmed.
|
|
38
|
-
* Rejects if transaction fails to submit or validate.
|
|
39
|
-
*/
|
|
40
|
-
confirmed: Promise<void>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export enum TransactionTrackerEvent {
|
|
44
|
-
NewTransaction = 'new-transaction'
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type TransactionTrackerEvents = { 'new-transaction': OnTransactionArgs };
|
|
48
|
-
export interface TransactionTracker extends Emittery<TransactionTrackerEvents> {
|
|
49
|
-
/**
|
|
50
|
-
* Track a new transaction.
|
|
51
|
-
*
|
|
52
|
-
* @param {CSL.Transaction} transaction transaction to track.
|
|
53
|
-
* @param {Promise<void>} submitted defer checking for transaction confirmation until this resolves.
|
|
54
|
-
*/
|
|
55
|
-
track(transaction: CSL.Transaction, submitted?: Promise<void>): Promise<void>;
|
|
56
|
-
}
|
package/test/.eslintrc.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Ogmios } from '@cardano-sdk/core';
|
|
2
|
-
import { MockUtxoRepository } from './mocks';
|
|
3
|
-
import { BalanceTracker, UtxoRepositoryEvent, UtxoRepositoryFields } from '../src';
|
|
4
|
-
|
|
5
|
-
const numAssets = (tokenMap?: Ogmios.TokenMap) => Object.keys(tokenMap || {}).length;
|
|
6
|
-
|
|
7
|
-
describe('BalanceTracker', () => {
|
|
8
|
-
let balanceTracker: BalanceTracker;
|
|
9
|
-
let utxoRepository: MockUtxoRepository;
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
utxoRepository = new MockUtxoRepository();
|
|
13
|
-
balanceTracker = new BalanceTracker(utxoRepository);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('constructor sets balances from utxo repository', () => {
|
|
17
|
-
expect(balanceTracker.total.coins).toBeGreaterThan(0n);
|
|
18
|
-
expect(balanceTracker.total.assets).toBeTruthy();
|
|
19
|
-
expect(balanceTracker.total.rewards).toBeGreaterThan(0n);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('updates balances on UtxoRepositoryEvent.Changed', async () => {
|
|
23
|
-
const totalBefore = balanceTracker.total;
|
|
24
|
-
|
|
25
|
-
const allRewards = utxoRepository.allRewards - 1n;
|
|
26
|
-
const availableRewards = utxoRepository.allRewards - 2n;
|
|
27
|
-
await utxoRepository.emit(UtxoRepositoryEvent.Changed, {
|
|
28
|
-
allUtxos: utxoRepository.allUtxos.slice(1),
|
|
29
|
-
availableUtxos: utxoRepository.allUtxos.slice(2),
|
|
30
|
-
allRewards,
|
|
31
|
-
availableRewards,
|
|
32
|
-
delegation: null
|
|
33
|
-
} as UtxoRepositoryFields);
|
|
34
|
-
|
|
35
|
-
expect(balanceTracker.total.coins).toBeLessThan(totalBefore.coins);
|
|
36
|
-
expect(balanceTracker.total.coins).toBeGreaterThan(balanceTracker.available.coins);
|
|
37
|
-
|
|
38
|
-
expect(numAssets(balanceTracker.total.assets)).toBeLessThan(numAssets(totalBefore.assets));
|
|
39
|
-
expect(numAssets(balanceTracker.total.assets)).toBeGreaterThan(numAssets(balanceTracker.available.assets));
|
|
40
|
-
|
|
41
|
-
expect(balanceTracker.total.rewards).toBe(allRewards);
|
|
42
|
-
expect(balanceTracker.available.rewards).toBe(availableRewards);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { CardanoSerializationLib, CSL, ProviderError, ProviderFailure } from '@cardano-sdk/core';
|
|
2
|
-
import { dummyLogger } from 'ts-log';
|
|
3
|
-
import { ledgerTip, providerStub, ProviderStub, queryTransactionsResult } from './mocks';
|
|
4
|
-
import mockDelay from 'delay';
|
|
5
|
-
import { TransactionTrackerEvent, InMemoryTransactionTracker, TransactionFailure } from '../src';
|
|
6
|
-
|
|
7
|
-
jest.mock('delay', () => jest.fn().mockResolvedValue(void 0));
|
|
8
|
-
|
|
9
|
-
describe('InMemoryTransactionTracker', () => {
|
|
10
|
-
const POLL_INTERVAL = 1000;
|
|
11
|
-
let ledgerTipSlot: number;
|
|
12
|
-
let provider: ProviderStub;
|
|
13
|
-
let txTracker: InMemoryTransactionTracker;
|
|
14
|
-
let hash_transaction: jest.Mock;
|
|
15
|
-
|
|
16
|
-
const mockHashTransactionReturn = (resultHash: string) => {
|
|
17
|
-
hash_transaction.mockReturnValue({
|
|
18
|
-
to_bytes() {
|
|
19
|
-
return Buffer.from(resultHash);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
provider = providerStub();
|
|
26
|
-
provider.queryTransactionsByHashes.mockReturnValue([queryTransactionsResult[0]]);
|
|
27
|
-
hash_transaction = jest.fn();
|
|
28
|
-
mockHashTransactionReturn('some-hash');
|
|
29
|
-
txTracker = new InMemoryTransactionTracker({
|
|
30
|
-
provider,
|
|
31
|
-
csl: { hash_transaction } as unknown as CardanoSerializationLib,
|
|
32
|
-
logger: dummyLogger,
|
|
33
|
-
pollInterval: POLL_INTERVAL
|
|
34
|
-
});
|
|
35
|
-
ledgerTipSlot = ledgerTip.slot;
|
|
36
|
-
(mockDelay as unknown as jest.Mock).mockReset();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe('track', () => {
|
|
40
|
-
let onTransaction: jest.Mock;
|
|
41
|
-
|
|
42
|
-
beforeEach(() => {
|
|
43
|
-
onTransaction = jest.fn();
|
|
44
|
-
txTracker.on(TransactionTrackerEvent.NewTransaction, onTransaction);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('cannot track transactions that have no validity interval', async () => {
|
|
48
|
-
await expect(() =>
|
|
49
|
-
txTracker.track({
|
|
50
|
-
body: () => ({
|
|
51
|
-
ttl: () => void 0
|
|
52
|
-
})
|
|
53
|
-
} as unknown as CSL.Transaction)
|
|
54
|
-
).rejects.toThrowError(TransactionFailure.CannotTrack);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe('valid transaction', () => {
|
|
58
|
-
let transaction: CSL.Transaction;
|
|
59
|
-
|
|
60
|
-
beforeEach(async () => {
|
|
61
|
-
transaction = {
|
|
62
|
-
body: () => ({
|
|
63
|
-
ttl: () => ledgerTipSlot
|
|
64
|
-
})
|
|
65
|
-
} as unknown as CSL.Transaction;
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('throws CannotTrack on ledger tip fetch error', async () => {
|
|
69
|
-
provider.queryTransactionsByHashes.mockResolvedValueOnce([]);
|
|
70
|
-
provider.ledgerTip.mockRejectedValueOnce(new ProviderError(ProviderFailure.Unknown));
|
|
71
|
-
await expect(txTracker.track(transaction)).rejects.toThrowError(TransactionFailure.CannotTrack);
|
|
72
|
-
expect(provider.ledgerTip).toBeCalledTimes(1);
|
|
73
|
-
expect(provider.queryTransactionsByHashes).toBeCalledTimes(1);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('polls provider at "pollInterval" until it returns the transaction', async () => {
|
|
77
|
-
// resolve [] or reject with 404 should be treated the same
|
|
78
|
-
provider.queryTransactionsByHashes.mockResolvedValueOnce([]);
|
|
79
|
-
provider.queryTransactionsByHashes.mockRejectedValueOnce(new ProviderError(ProviderFailure.NotFound));
|
|
80
|
-
await txTracker.track(transaction);
|
|
81
|
-
expect(provider.queryTransactionsByHashes).toBeCalledTimes(3);
|
|
82
|
-
expect(mockDelay).toBeCalledTimes(3);
|
|
83
|
-
expect(mockDelay).toBeCalledWith(POLL_INTERVAL);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('throws after timeout', async () => {
|
|
87
|
-
provider.queryTransactionsByHashes.mockResolvedValueOnce([]);
|
|
88
|
-
provider.ledgerTip.mockResolvedValueOnce({ slot: ledgerTipSlot + 1 });
|
|
89
|
-
await expect(txTracker.track(transaction)).rejects.toThrowError(TransactionFailure.Timeout);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('emits "transaction" event for tracked transactions, returns promise unique per pending tx', async () => {
|
|
93
|
-
const promise1 = txTracker.track(transaction);
|
|
94
|
-
const promise2 = txTracker.track(transaction);
|
|
95
|
-
await promise1;
|
|
96
|
-
await promise2;
|
|
97
|
-
mockHashTransactionReturn('other-hash');
|
|
98
|
-
await txTracker.track(transaction);
|
|
99
|
-
expect(provider.queryTransactionsByHashes).toBeCalledTimes(2);
|
|
100
|
-
expect(onTransaction).toBeCalledTimes(2);
|
|
101
|
-
// assert it clears cache
|
|
102
|
-
await txTracker.track(transaction);
|
|
103
|
-
expect(provider.queryTransactionsByHashes).toBeCalledTimes(3);
|
|
104
|
-
expect(onTransaction).toBeCalledTimes(3);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
});
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
/* eslint-disable unicorn/consistent-function-scoping */
|
|
2
|
-
/* eslint-disable promise/param-names */
|
|
3
|
-
import { roundRobinRandomImprove, InputSelector } from '@cardano-sdk/cip2';
|
|
4
|
-
import { loadCardanoSerializationLib, CardanoSerializationLib, CSL, Ogmios, Cardano } from '@cardano-sdk/core';
|
|
5
|
-
import { flushPromises, SelectionConstraints } from '@cardano-sdk/util-dev';
|
|
6
|
-
import {
|
|
7
|
-
providerStub,
|
|
8
|
-
delegate,
|
|
9
|
-
rewards,
|
|
10
|
-
ProviderStub,
|
|
11
|
-
utxo,
|
|
12
|
-
delegationAndRewards,
|
|
13
|
-
MockTransactionTracker
|
|
14
|
-
} from './mocks';
|
|
15
|
-
import {
|
|
16
|
-
InMemoryUtxoRepository,
|
|
17
|
-
KeyManagement,
|
|
18
|
-
TransactionTrackerEvent,
|
|
19
|
-
UtxoRepository,
|
|
20
|
-
UtxoRepositoryEvent,
|
|
21
|
-
UtxoRepositoryFields
|
|
22
|
-
} from '../src';
|
|
23
|
-
import { ogmiosToCsl } from '@cardano-sdk/core/src/Ogmios';
|
|
24
|
-
import { TxIn, TxOut } from '@cardano-ogmios/schema';
|
|
25
|
-
import { TransactionError, TransactionFailure } from '../src/TransactionError';
|
|
26
|
-
|
|
27
|
-
const addresses = [
|
|
28
|
-
'addr_test1qq585l3hyxgj3nas2v3xymd23vvartfhceme6gv98aaeg9muzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475q2g7k3g'
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
describe('InMemoryUtxoRepository', () => {
|
|
32
|
-
let utxoRepository: UtxoRepository;
|
|
33
|
-
let provider: ProviderStub;
|
|
34
|
-
let inputSelector: InputSelector;
|
|
35
|
-
let csl: CardanoSerializationLib;
|
|
36
|
-
let keyManager: KeyManagement.KeyManager;
|
|
37
|
-
let outputs: Set<CSL.TransactionOutput>;
|
|
38
|
-
let txTracker: MockTransactionTracker;
|
|
39
|
-
|
|
40
|
-
beforeEach(async () => {
|
|
41
|
-
provider = providerStub();
|
|
42
|
-
csl = await loadCardanoSerializationLib();
|
|
43
|
-
inputSelector = roundRobinRandomImprove(csl);
|
|
44
|
-
keyManager = KeyManagement.createInMemoryKeyManager({
|
|
45
|
-
csl,
|
|
46
|
-
mnemonicWords: KeyManagement.util.generateMnemonicWords(),
|
|
47
|
-
networkId: 0,
|
|
48
|
-
password: '123'
|
|
49
|
-
});
|
|
50
|
-
outputs = new Set([
|
|
51
|
-
Ogmios.ogmiosToCsl(csl).txOut({
|
|
52
|
-
address: addresses[0],
|
|
53
|
-
value: { coins: 4_000_000 }
|
|
54
|
-
}),
|
|
55
|
-
Ogmios.ogmiosToCsl(csl).txOut({
|
|
56
|
-
address: addresses[0],
|
|
57
|
-
value: { coins: 2_000_000 }
|
|
58
|
-
})
|
|
59
|
-
]);
|
|
60
|
-
txTracker = new MockTransactionTracker();
|
|
61
|
-
utxoRepository = new InMemoryUtxoRepository({
|
|
62
|
-
csl,
|
|
63
|
-
provider,
|
|
64
|
-
keyManager,
|
|
65
|
-
inputSelector,
|
|
66
|
-
txTracker
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('constructed state', async () => {
|
|
71
|
-
expect(utxoRepository.allUtxos.length).toBe(0);
|
|
72
|
-
expect(utxoRepository.allRewards).toBe(null);
|
|
73
|
-
expect(utxoRepository.delegation).toBe(null);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('sync', async () => {
|
|
77
|
-
const syncedHandler = jest.fn();
|
|
78
|
-
utxoRepository.on(UtxoRepositoryEvent.Changed, syncedHandler);
|
|
79
|
-
await utxoRepository.sync();
|
|
80
|
-
const expectedFields: UtxoRepositoryFields = {
|
|
81
|
-
allUtxos: utxo,
|
|
82
|
-
availableUtxos: utxo,
|
|
83
|
-
allRewards: rewards,
|
|
84
|
-
availableRewards: rewards,
|
|
85
|
-
delegation: delegate
|
|
86
|
-
};
|
|
87
|
-
expect(utxoRepository).toMatchObject(expectedFields);
|
|
88
|
-
expect(syncedHandler).toBeCalledTimes(1);
|
|
89
|
-
expect(syncedHandler).toBeCalledWith(expectedFields);
|
|
90
|
-
const identicalUtxo = [{ ...utxo[1][0] }, { ...utxo[1][1] }] as const; // clone UTxO
|
|
91
|
-
provider.utxoDelegationAndRewards.mockResolvedValueOnce({
|
|
92
|
-
utxo: [utxo[0], identicalUtxo],
|
|
93
|
-
delegationAndRewards
|
|
94
|
-
});
|
|
95
|
-
await utxoRepository.sync();
|
|
96
|
-
expect(utxoRepository.allUtxos.length).toBe(2);
|
|
97
|
-
// Verify we're not replacing the object with an identical one in the UTxO set
|
|
98
|
-
expect(utxoRepository.allUtxos).not.toContain(identicalUtxo);
|
|
99
|
-
expect(utxoRepository.allUtxos).toContain(utxo[1]);
|
|
100
|
-
expect(syncedHandler).toBeCalledTimes(2);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
describe('selectInputs', () => {
|
|
104
|
-
it('can be called without explicitly syncing', async () => {
|
|
105
|
-
const result = await utxoRepository.selectInputs(outputs, SelectionConstraints.NO_CONSTRAINTS);
|
|
106
|
-
expect(utxoRepository.allUtxos.length).toBe(3);
|
|
107
|
-
expect(utxoRepository.allRewards).toBe(rewards);
|
|
108
|
-
expect(utxoRepository.delegation).toBe(delegate);
|
|
109
|
-
expect(result.selection.inputs.size).toBeGreaterThan(0);
|
|
110
|
-
expect(result.selection.outputs).toBe(outputs);
|
|
111
|
-
expect(result.selection.change.size).toBe(2);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
describe('availableUtxos and availableRewards', () => {
|
|
116
|
-
let transactionUtxo: [TxIn, TxOut];
|
|
117
|
-
let transaction: CSL.Transaction;
|
|
118
|
-
let numUtxoPreTransaction: number;
|
|
119
|
-
let rewardsPreTransaction: bigint;
|
|
120
|
-
let onOutOfSync: jest.Mock;
|
|
121
|
-
let completeConfirmation: Function;
|
|
122
|
-
const transactionWithdrawal = 1n;
|
|
123
|
-
|
|
124
|
-
const trackTransaction = async (confirmed: Promise<void>) => {
|
|
125
|
-
const syncedHandler = jest.fn();
|
|
126
|
-
utxoRepository.on(UtxoRepositoryEvent.Changed, syncedHandler);
|
|
127
|
-
await txTracker.emit(TransactionTrackerEvent.NewTransaction, {
|
|
128
|
-
transaction,
|
|
129
|
-
confirmed
|
|
130
|
-
});
|
|
131
|
-
// transaction not yet confirmed
|
|
132
|
-
expect(utxoRepository.availableUtxos).toHaveLength(utxoRepository.allUtxos.length - 1);
|
|
133
|
-
expect(utxoRepository.availableUtxos).not.toContain(transactionUtxo);
|
|
134
|
-
expect(syncedHandler).toBeCalledTimes(1);
|
|
135
|
-
expect(syncedHandler).toBeCalledWith({
|
|
136
|
-
allUtxos: utxo,
|
|
137
|
-
availableUtxos: utxo.slice(1),
|
|
138
|
-
allRewards: rewards,
|
|
139
|
-
availableRewards: rewards - transactionWithdrawal,
|
|
140
|
-
delegation: delegate
|
|
141
|
-
} as UtxoRepositoryFields);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const assertThereAreNoPendingTransactionsOrRewards = () => {
|
|
145
|
-
expect(utxoRepository.availableUtxos).toHaveLength(utxoRepository.allUtxos.length);
|
|
146
|
-
expect(utxoRepository.allRewards).toBe(utxoRepository.availableRewards);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
beforeEach(async () => {
|
|
150
|
-
transactionUtxo = utxo[0];
|
|
151
|
-
transaction = {
|
|
152
|
-
body: () => ({
|
|
153
|
-
inputs: () => ({
|
|
154
|
-
len: () => 1,
|
|
155
|
-
get: () => ogmiosToCsl(csl).txIn(transactionUtxo[0])
|
|
156
|
-
}),
|
|
157
|
-
withdrawals: () => ({
|
|
158
|
-
keys: () => ({
|
|
159
|
-
len: () => 1,
|
|
160
|
-
get: () =>
|
|
161
|
-
csl.RewardAddress.new(
|
|
162
|
-
Cardano.NetworkId.testnet,
|
|
163
|
-
csl.StakeCredential.from_keyhash(keyManager.stakeKey.hash())
|
|
164
|
-
)
|
|
165
|
-
}),
|
|
166
|
-
len: () => 1,
|
|
167
|
-
get: () => csl.BigNum.from_str(transactionWithdrawal.toString())
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
} as unknown as CSL.Transaction;
|
|
171
|
-
await utxoRepository.sync();
|
|
172
|
-
numUtxoPreTransaction = utxoRepository.allUtxos.length;
|
|
173
|
-
rewardsPreTransaction = utxoRepository.allRewards!;
|
|
174
|
-
onOutOfSync = jest.fn();
|
|
175
|
-
utxoRepository.on(UtxoRepositoryEvent.OutOfSync, onOutOfSync);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('preconditions', () => {
|
|
179
|
-
expect(utxoRepository.availableUtxos).toHaveLength(utxoRepository.allUtxos.length);
|
|
180
|
-
expect(utxoRepository.availableUtxos).toContain(transactionUtxo);
|
|
181
|
-
expect(utxoRepository.availableRewards).toBe(rewardsPreTransaction);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
describe('sync success', () => {
|
|
185
|
-
beforeEach(() => {
|
|
186
|
-
// Simulate spent utxo and rewards
|
|
187
|
-
expect(provider.utxoDelegationAndRewards).toBeCalledTimes(1);
|
|
188
|
-
provider.utxoDelegationAndRewards.mockResolvedValueOnce({
|
|
189
|
-
utxo: utxo.slice(1),
|
|
190
|
-
delegationAndRewards: {
|
|
191
|
-
...delegationAndRewards,
|
|
192
|
-
rewards: rewards - transactionWithdrawal
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
const confirmTxAndAssertUtxoRepositorySynced = async () => {
|
|
198
|
-
await completeConfirmation!();
|
|
199
|
-
await flushPromises();
|
|
200
|
-
// Assert values from provider sync
|
|
201
|
-
expect(provider.utxoDelegationAndRewards).toBeCalledTimes(2);
|
|
202
|
-
expect(utxoRepository.availableUtxos).toHaveLength(numUtxoPreTransaction - 1);
|
|
203
|
-
expect(utxoRepository.availableUtxos).not.toContain(transactionUtxo);
|
|
204
|
-
expect(utxoRepository.availableRewards).toBe(rewardsPreTransaction - transactionWithdrawal);
|
|
205
|
-
expect(onOutOfSync).not.toBeCalled();
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
it('transaction confirmed', async () => {
|
|
209
|
-
await trackTransaction(new Promise<void>((resolve) => (completeConfirmation = resolve)));
|
|
210
|
-
await confirmTxAndAssertUtxoRepositorySynced();
|
|
211
|
-
assertThereAreNoPendingTransactionsOrRewards();
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('transaction confirmation failed', async () => {
|
|
215
|
-
// setup for transaction to timeout
|
|
216
|
-
await trackTransaction(
|
|
217
|
-
new Promise<void>(
|
|
218
|
-
(_, reject) => (completeConfirmation = () => reject(new TransactionError(TransactionFailure.Timeout)))
|
|
219
|
-
)
|
|
220
|
-
);
|
|
221
|
-
await confirmTxAndAssertUtxoRepositorySynced();
|
|
222
|
-
assertThereAreNoPendingTransactionsOrRewards();
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('emits OutOfSync on sync failure', async () => {
|
|
227
|
-
provider.utxoDelegationAndRewards.mockRejectedValueOnce(new Error('any error'));
|
|
228
|
-
|
|
229
|
-
const confirmed = new Promise<void>((resolve) => (completeConfirmation = resolve));
|
|
230
|
-
await trackTransaction(confirmed);
|
|
231
|
-
|
|
232
|
-
// transaction confirmed
|
|
233
|
-
await completeConfirmation!();
|
|
234
|
-
await flushPromises();
|
|
235
|
-
expect(utxoRepository.availableUtxos).toHaveLength(numUtxoPreTransaction);
|
|
236
|
-
expect(utxoRepository.availableUtxos).toContain(transactionUtxo);
|
|
237
|
-
expect(utxoRepository.allRewards).toBe(rewardsPreTransaction);
|
|
238
|
-
expect(onOutOfSync).toBeCalledTimes(1);
|
|
239
|
-
assertThereAreNoPendingTransactionsOrRewards();
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
});
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Cardano, CardanoSerializationLib, loadCardanoSerializationLib } from '@cardano-sdk/core';
|
|
2
|
-
import { Buffer } from 'buffer';
|
|
3
|
-
import { KeyManagement } from '../../src';
|
|
4
|
-
|
|
5
|
-
describe('InMemoryKeyManager', () => {
|
|
6
|
-
let keyManager: KeyManagement.KeyManager;
|
|
7
|
-
let csl: CardanoSerializationLib;
|
|
8
|
-
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
csl = await loadCardanoSerializationLib();
|
|
11
|
-
const mnemonicWords = KeyManagement.util.generateMnemonicWords();
|
|
12
|
-
keyManager = KeyManagement.createInMemoryKeyManager({
|
|
13
|
-
csl,
|
|
14
|
-
mnemonicWords,
|
|
15
|
-
networkId: Cardano.NetworkId.testnet,
|
|
16
|
-
password: '123'
|
|
17
|
-
});
|
|
18
|
-
expect(keyManager.publicKey).toBeInstanceOf(csl.PublicKey);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('initial state publicKey', async () => {
|
|
22
|
-
expect(keyManager.publicKey).toBeDefined();
|
|
23
|
-
expect(keyManager.publicParentKey).toBeDefined();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('deriveAddress', async () => {
|
|
27
|
-
const address = await keyManager.deriveAddress(0, 0);
|
|
28
|
-
expect(address).toBeDefined();
|
|
29
|
-
expect(keyManager.publicParentKey).toBeDefined();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('signTransaction', async () => {
|
|
33
|
-
const txHash = csl.TransactionHash.from_bytes(
|
|
34
|
-
Buffer.from('8561258e210352fba2ac0488afed67b3427a27ccf1d41ec030c98a8199bc22ec', 'hex')
|
|
35
|
-
);
|
|
36
|
-
const witnessSet = await keyManager.signTransaction(txHash);
|
|
37
|
-
expect(witnessSet).toBeInstanceOf(csl.TransactionWitnessSet);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-len */
|
|
2
|
-
import { loadCardanoSerializationLib, CardanoSerializationLib, Cardano } from '@cardano-sdk/core';
|
|
3
|
-
import { InputSelector, roundRobinRandomImprove } from '@cardano-sdk/cip2';
|
|
4
|
-
import { ProviderStub, providerStub, txTracker } from './mocks';
|
|
5
|
-
import {
|
|
6
|
-
BalanceTracker,
|
|
7
|
-
createSingleAddressWallet,
|
|
8
|
-
InMemoryUtxoRepository,
|
|
9
|
-
KeyManagement,
|
|
10
|
-
SingleAddressWallet,
|
|
11
|
-
SingleAddressWalletDependencies,
|
|
12
|
-
UtxoRepository
|
|
13
|
-
} from '../src';
|
|
14
|
-
|
|
15
|
-
describe('Wallet', () => {
|
|
16
|
-
const name = 'Test Wallet';
|
|
17
|
-
let csl: CardanoSerializationLib;
|
|
18
|
-
let inputSelector: InputSelector;
|
|
19
|
-
let keyManager: KeyManagement.KeyManager;
|
|
20
|
-
let provider: ProviderStub;
|
|
21
|
-
let utxoRepository: UtxoRepository;
|
|
22
|
-
let walletDependencies: SingleAddressWalletDependencies;
|
|
23
|
-
|
|
24
|
-
beforeEach(async () => {
|
|
25
|
-
csl = await loadCardanoSerializationLib();
|
|
26
|
-
keyManager = KeyManagement.createInMemoryKeyManager({
|
|
27
|
-
csl,
|
|
28
|
-
mnemonicWords: KeyManagement.util.generateMnemonicWords(),
|
|
29
|
-
networkId: Cardano.NetworkId.testnet,
|
|
30
|
-
password: '123'
|
|
31
|
-
});
|
|
32
|
-
provider = providerStub();
|
|
33
|
-
inputSelector = roundRobinRandomImprove(csl);
|
|
34
|
-
utxoRepository = new InMemoryUtxoRepository({ csl, provider, keyManager, inputSelector, txTracker });
|
|
35
|
-
walletDependencies = { csl, keyManager, provider, utxoRepository, txTracker };
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('createWallet', async () => {
|
|
39
|
-
const wallet = await createSingleAddressWallet({ name }, walletDependencies);
|
|
40
|
-
expect(wallet.address).toBeDefined();
|
|
41
|
-
expect(wallet.name).toBe(name);
|
|
42
|
-
expect(typeof wallet.initializeTx).toBe('function');
|
|
43
|
-
expect(typeof wallet.signTx).toBe('function');
|
|
44
|
-
expect(wallet.balance).toBeInstanceOf(BalanceTracker);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe('wallet behaviour', () => {
|
|
48
|
-
let wallet: SingleAddressWallet;
|
|
49
|
-
const props = {
|
|
50
|
-
outputs: new Set([
|
|
51
|
-
{
|
|
52
|
-
address:
|
|
53
|
-
'addr_test1qpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qum8x5w',
|
|
54
|
-
value: { coins: 11_111_111 }
|
|
55
|
-
}
|
|
56
|
-
])
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
beforeEach(async () => {
|
|
60
|
-
wallet = await createSingleAddressWallet({ name }, walletDependencies);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('initializeTx', async () => {
|
|
64
|
-
const txInternals = await wallet.initializeTx(props);
|
|
65
|
-
expect(txInternals.body).toBeInstanceOf(csl.TransactionBody);
|
|
66
|
-
expect(txInternals.hash).toBeInstanceOf(csl.TransactionHash);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('signTx', async () => {
|
|
70
|
-
const { body, hash } = await wallet.initializeTx(props);
|
|
71
|
-
const tx = await wallet.signTx(body, hash);
|
|
72
|
-
await expect(tx.body().outputs().len()).toBe(2);
|
|
73
|
-
await expect(tx.body().inputs().len()).toBeGreaterThan(0);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('submitTx', async () => {
|
|
77
|
-
const { body, hash } = await wallet.initializeTx(props);
|
|
78
|
-
const tx = await wallet.signTx(body, hash);
|
|
79
|
-
const { submitted, confirmed } = wallet.submitTx(tx);
|
|
80
|
-
await confirmed;
|
|
81
|
-
expect(provider.submitTx).toBeCalledTimes(1);
|
|
82
|
-
expect(provider.submitTx).toBeCalledWith(tx);
|
|
83
|
-
expect(txTracker.track).toBeCalledTimes(1);
|
|
84
|
-
expect(txTracker.track).toBeCalledWith(tx, submitted);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
});
|