@cardano-sdk/wallet 0.1.4 → 0.1.5
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/dist/Address.d.ts +11 -0
- package/dist/Address.d.ts.map +1 -0
- package/dist/Address.js +9 -0
- package/dist/Address.js.map +1 -0
- package/dist/BalanceTracker.d.ts +23 -0
- package/dist/BalanceTracker.d.ts.map +1 -0
- package/dist/BalanceTracker.js +48 -0
- package/dist/BalanceTracker.js.map +1 -0
- package/dist/InMemoryTransactionTracker.d.ts +16 -0
- package/dist/InMemoryTransactionTracker.d.ts.map +1 -0
- package/dist/InMemoryTransactionTracker.js +84 -0
- package/dist/InMemoryTransactionTracker.js.map +1 -0
- package/dist/InMemoryUtxoRepository.d.ts +25 -0
- package/dist/InMemoryUtxoRepository.d.ts.map +1 -0
- package/dist/InMemoryUtxoRepository.js +154 -0
- package/dist/InMemoryUtxoRepository.js.map +1 -0
- package/dist/KeyManagement/InMemoryKeyManager.d.ts +9 -0
- package/dist/KeyManagement/InMemoryKeyManager.d.ts.map +1 -0
- package/dist/KeyManagement/InMemoryKeyManager.js +68 -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 +14 -0
- package/dist/KeyManagement/types.d.ts.map +1 -0
- package/dist/KeyManagement/types.js +3 -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 +30 -0
- package/dist/SingleAddressWallet.d.ts.map +1 -0
- package/dist/SingleAddressWallet.js +62 -0
- package/dist/SingleAddressWallet.js.map +1 -0
- package/dist/Transaction/CertificateFactory.d.ts +50 -0
- package/dist/Transaction/CertificateFactory.d.ts.map +1 -0
- package/dist/Transaction/CertificateFactory.js +72 -0
- package/dist/Transaction/CertificateFactory.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 +41 -0
- package/dist/Transaction/createTransactionInternals.js.map +1 -0
- package/{src/Transaction/index.ts → dist/Transaction/index.d.ts} +1 -0
- package/dist/Transaction/index.d.ts.map +1 -0
- package/dist/Transaction/index.js +18 -0
- package/dist/Transaction/index.js.map +1 -0
- package/dist/Transaction/types.d.ts +11 -0
- package/dist/Transaction/types.d.ts.map +1 -0
- package/dist/Transaction/types.js +3 -0
- package/dist/Transaction/types.js.map +1 -0
- package/dist/Transaction/withdrawal.d.ts +8 -0
- package/dist/Transaction/withdrawal.d.ts.map +1 -0
- package/dist/Transaction/withdrawal.js +10 -0
- package/dist/Transaction/withdrawal.js.map +1 -0
- package/dist/TransactionError.d.ts +15 -0
- package/dist/TransactionError.d.ts.map +1 -0
- package/dist/TransactionError.js +23 -0
- package/dist/TransactionError.js.map +1 -0
- package/{src/index.ts → dist/index.d.ts} +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +13 -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/types.ts +0 -12
- package/src/Transaction/withdrawal.ts +0 -17
- package/src/TransactionError.ts +0 -17
- 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,67 +0,0 @@
|
|
|
1
|
-
import * as bip39 from 'isomorphic-bip39';
|
|
2
|
-
import { Cardano, CardanoSerializationLib, CSL } from '@cardano-sdk/core';
|
|
3
|
-
import { Buffer } from 'buffer';
|
|
4
|
-
import * as errors from './errors';
|
|
5
|
-
import { KeyManager } from './types';
|
|
6
|
-
import { harden, joinMnemonicWords } from './util';
|
|
7
|
-
|
|
8
|
-
export const createInMemoryKeyManager = ({
|
|
9
|
-
csl,
|
|
10
|
-
password,
|
|
11
|
-
accountIndex,
|
|
12
|
-
mnemonicWords,
|
|
13
|
-
networkId
|
|
14
|
-
}: {
|
|
15
|
-
csl: CardanoSerializationLib;
|
|
16
|
-
password: string;
|
|
17
|
-
accountIndex?: number;
|
|
18
|
-
mnemonicWords: string[];
|
|
19
|
-
networkId: Cardano.NetworkId;
|
|
20
|
-
}): KeyManager => {
|
|
21
|
-
if (!accountIndex) {
|
|
22
|
-
accountIndex = 0;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const mnemonic = joinMnemonicWords(mnemonicWords);
|
|
26
|
-
const validMnemonic = bip39.validateMnemonic(mnemonic);
|
|
27
|
-
if (!validMnemonic) throw new errors.InvalidMnemonic();
|
|
28
|
-
|
|
29
|
-
const entropy = bip39.mnemonicToEntropy(mnemonic);
|
|
30
|
-
const accountPrivateKey = csl.Bip32PrivateKey.from_bip39_entropy(Buffer.from(entropy, 'hex'), Buffer.from(password))
|
|
31
|
-
.derive(harden(1852))
|
|
32
|
-
.derive(harden(1815))
|
|
33
|
-
.derive(harden(accountIndex));
|
|
34
|
-
|
|
35
|
-
const privateParentKey = accountPrivateKey.derive(0).derive(0);
|
|
36
|
-
const publicParentKey = privateParentKey.to_public();
|
|
37
|
-
const publicKey = accountPrivateKey.to_public();
|
|
38
|
-
const stakeKey = publicKey.derive(2).derive(0);
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
deriveAddress: (addressIndex, index) => {
|
|
42
|
-
const utxoPubKey = publicKey.derive(index).derive(addressIndex);
|
|
43
|
-
const baseAddr = csl.BaseAddress.new(
|
|
44
|
-
networkId,
|
|
45
|
-
csl.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()),
|
|
46
|
-
csl.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash())
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
return baseAddr.to_address().to_bech32();
|
|
50
|
-
},
|
|
51
|
-
signMessage: async (_addressType, _signingIndex, message) => ({
|
|
52
|
-
publicKey: publicParentKey.toString(),
|
|
53
|
-
signature: `Signature for ${message} is not implemented yet`
|
|
54
|
-
}),
|
|
55
|
-
signTransaction: async (txHash: CSL.TransactionHash) => {
|
|
56
|
-
const witnessSet = csl.TransactionWitnessSet.new();
|
|
57
|
-
const vkeyWitnesses = csl.Vkeywitnesses.new();
|
|
58
|
-
const vkeyWitness = csl.make_vkey_witness(txHash, privateParentKey.to_raw_key());
|
|
59
|
-
vkeyWitnesses.add(vkeyWitness);
|
|
60
|
-
witnessSet.set_vkeys(vkeyWitnesses);
|
|
61
|
-
return witnessSet;
|
|
62
|
-
},
|
|
63
|
-
stakeKey: stakeKey.to_raw_key(),
|
|
64
|
-
publicKey: publicKey.to_raw_key(),
|
|
65
|
-
publicParentKey: publicParentKey.to_raw_key()
|
|
66
|
-
};
|
|
67
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { CSL } from '@cardano-sdk/core';
|
|
2
|
-
import { Address } from '..';
|
|
3
|
-
|
|
4
|
-
export interface KeyManager {
|
|
5
|
-
deriveAddress: (addressIndex: number, index: 0 | 1) => string;
|
|
6
|
-
signMessage: (
|
|
7
|
-
addressType: Address.AddressType,
|
|
8
|
-
signingIndex: number,
|
|
9
|
-
message: string
|
|
10
|
-
) => Promise<{ publicKey: string; signature: string }>;
|
|
11
|
-
publicKey: CSL.PublicKey;
|
|
12
|
-
publicParentKey: CSL.PublicKey;
|
|
13
|
-
signTransaction: (txHash: CSL.TransactionHash) => Promise<CSL.TransactionWitnessSet>;
|
|
14
|
-
stakeKey: CSL.PublicKey;
|
|
15
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import * as bip39 from 'isomorphic-bip39';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A wrapper around the bip39 package function, with default strength applied to produce 24 words
|
|
5
|
-
*/
|
|
6
|
-
export const generateMnemonicWords = (strength = 256) => bip39.generateMnemonic(strength).split(' ');
|
|
7
|
-
export const joinMnemonicWords = (mnenomic: string[]) => mnenomic.join(' ');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* A wrapper around the bip39 package function
|
|
11
|
-
*/
|
|
12
|
-
export const validateMnemonic = bip39.validateMnemonic;
|
|
13
|
-
|
|
14
|
-
export const harden = (num: number): number => 0x80_00_00_00 + num;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import Schema from '@cardano-ogmios/schema';
|
|
2
|
-
import { CardanoProvider, Ogmios, Transaction, CardanoSerializationLib, CSL, ProviderError } from '@cardano-sdk/core';
|
|
3
|
-
import { UtxoRepository } from './types';
|
|
4
|
-
import { dummyLogger, Logger } from 'ts-log';
|
|
5
|
-
import { defaultSelectionConstraints } from '@cardano-sdk/cip2';
|
|
6
|
-
import { computeImplicitCoin, createTransactionInternals, InitializeTxProps, TxInternals } from './Transaction';
|
|
7
|
-
import {
|
|
8
|
-
BalanceTracker,
|
|
9
|
-
InMemoryTransactionTracker,
|
|
10
|
-
KeyManagement,
|
|
11
|
-
TransactionError,
|
|
12
|
-
TransactionFailure,
|
|
13
|
-
TransactionTracker
|
|
14
|
-
} from '.';
|
|
15
|
-
|
|
16
|
-
export interface SubmitTxResult {
|
|
17
|
-
/**
|
|
18
|
-
* Resolves when transaction is submitted.
|
|
19
|
-
* Rejects with {TransactionError}.
|
|
20
|
-
*/
|
|
21
|
-
submitted: Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* Resolves when transaction is submitted and confirmed.
|
|
24
|
-
* Rejects with {TransactionError}.
|
|
25
|
-
*/
|
|
26
|
-
confirmed: Promise<void>;
|
|
27
|
-
}
|
|
28
|
-
export interface SingleAddressWallet {
|
|
29
|
-
address: Schema.Address;
|
|
30
|
-
balance: BalanceTracker;
|
|
31
|
-
initializeTx: (props: InitializeTxProps) => Promise<TxInternals>;
|
|
32
|
-
name: string;
|
|
33
|
-
signTx: (body: CSL.TransactionBody, hash: CSL.TransactionHash) => Promise<CSL.Transaction>;
|
|
34
|
-
submitTx: (tx: CSL.Transaction) => SubmitTxResult;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface SingleAddressWalletDependencies {
|
|
38
|
-
csl: CardanoSerializationLib;
|
|
39
|
-
keyManager: KeyManagement.KeyManager;
|
|
40
|
-
logger?: Logger;
|
|
41
|
-
provider: CardanoProvider;
|
|
42
|
-
utxoRepository: UtxoRepository;
|
|
43
|
-
txTracker?: TransactionTracker;
|
|
44
|
-
balanceTracker?: BalanceTracker;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface SingleAddressWalletProps {
|
|
48
|
-
name: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const ensureValidityInterval = (
|
|
52
|
-
currentSlot: number,
|
|
53
|
-
validityInterval?: Transaction.ValidityInterval
|
|
54
|
-
): Transaction.ValidityInterval =>
|
|
55
|
-
// Todo: Based this on slot duration, to equal 2hrs
|
|
56
|
-
({ invalidHereafter: currentSlot + 3600, ...validityInterval });
|
|
57
|
-
|
|
58
|
-
export const createSingleAddressWallet = async (
|
|
59
|
-
{ name }: SingleAddressWalletProps,
|
|
60
|
-
{
|
|
61
|
-
csl,
|
|
62
|
-
provider,
|
|
63
|
-
keyManager,
|
|
64
|
-
utxoRepository,
|
|
65
|
-
txTracker = new InMemoryTransactionTracker({ csl, provider }),
|
|
66
|
-
balanceTracker = new BalanceTracker(utxoRepository),
|
|
67
|
-
logger = dummyLogger
|
|
68
|
-
}: SingleAddressWalletDependencies
|
|
69
|
-
): Promise<SingleAddressWallet> => {
|
|
70
|
-
const address = keyManager.deriveAddress(0, 0);
|
|
71
|
-
const protocolParameters = await provider.currentWalletProtocolParameters();
|
|
72
|
-
const signTx = async (body: CSL.TransactionBody, hash: CSL.TransactionHash) => {
|
|
73
|
-
const witnessSet = await keyManager.signTransaction(hash);
|
|
74
|
-
return csl.Transaction.new(body, witnessSet);
|
|
75
|
-
};
|
|
76
|
-
return {
|
|
77
|
-
address,
|
|
78
|
-
balance: balanceTracker,
|
|
79
|
-
initializeTx: async (props) => {
|
|
80
|
-
const tip = await provider.ledgerTip();
|
|
81
|
-
const validityInterval = ensureValidityInterval(tip.slot, props.options?.validityInterval);
|
|
82
|
-
const txOutputs = new Set([...props.outputs].map((output) => Ogmios.ogmiosToCsl(csl).txOut(output)));
|
|
83
|
-
const constraints = defaultSelectionConstraints({
|
|
84
|
-
csl,
|
|
85
|
-
protocolParameters,
|
|
86
|
-
buildTx: async (inputSelection) => {
|
|
87
|
-
logger.debug('Building TX for selection constraints', inputSelection);
|
|
88
|
-
const { body, hash } = await createTransactionInternals(csl, {
|
|
89
|
-
changeAddress: address,
|
|
90
|
-
inputSelection,
|
|
91
|
-
validityInterval
|
|
92
|
-
});
|
|
93
|
-
return signTx(body, hash);
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
const implicitCoin = computeImplicitCoin(protocolParameters, props);
|
|
97
|
-
const inputSelectionResult = await utxoRepository.selectInputs(txOutputs, constraints, implicitCoin);
|
|
98
|
-
return createTransactionInternals(csl, {
|
|
99
|
-
changeAddress: address,
|
|
100
|
-
inputSelection: inputSelectionResult.selection,
|
|
101
|
-
validityInterval
|
|
102
|
-
});
|
|
103
|
-
},
|
|
104
|
-
name,
|
|
105
|
-
signTx,
|
|
106
|
-
submitTx: (tx) => {
|
|
107
|
-
const submitted = provider.submitTx(tx).catch((error) => {
|
|
108
|
-
if (error instanceof ProviderError) {
|
|
109
|
-
throw new TransactionError(TransactionFailure.FailedToSubmit, error, error.detail);
|
|
110
|
-
}
|
|
111
|
-
throw new TransactionError(TransactionFailure.FailedToSubmit, error);
|
|
112
|
-
});
|
|
113
|
-
const confirmed = txTracker.track(tx, submitted);
|
|
114
|
-
return {
|
|
115
|
-
submitted,
|
|
116
|
-
confirmed
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
};
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { ByName } from '@cardano-ogmios/schema';
|
|
2
|
-
import { CardanoSerializationLib, CSL, NotImplementedError, Ogmios } from '@cardano-sdk/core';
|
|
3
|
-
import { KeyManager } from '../KeyManagement';
|
|
4
|
-
|
|
5
|
-
export type Ed25519KeyHashBech32 = string;
|
|
6
|
-
export type VrfKeyHashBech32 = string;
|
|
7
|
-
export type AddressBech32 = string;
|
|
8
|
-
export type PoolMetadataHashBech32 = string;
|
|
9
|
-
|
|
10
|
-
interface Ratio {
|
|
11
|
-
numerator: number;
|
|
12
|
-
denominator: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface MultiHostNameRelay {
|
|
16
|
-
relayType: 'multihost-name';
|
|
17
|
-
dnsName: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type SingleHostAddrRelay = {
|
|
21
|
-
relayType: 'singlehost-addr';
|
|
22
|
-
ipv4?: string;
|
|
23
|
-
ipv6?: string;
|
|
24
|
-
port?: number;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type SingleHostNameRelay = {
|
|
28
|
-
relayType: 'singlehost-name';
|
|
29
|
-
} & ByName;
|
|
30
|
-
|
|
31
|
-
type Relay = MultiHostNameRelay | SingleHostAddrRelay | SingleHostNameRelay;
|
|
32
|
-
|
|
33
|
-
interface PoolMetadata {
|
|
34
|
-
hash: PoolMetadataHashBech32;
|
|
35
|
-
url: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface PoolParameters {
|
|
39
|
-
poolKeyHash: Ed25519KeyHashBech32;
|
|
40
|
-
vrfKeyHash: VrfKeyHashBech32;
|
|
41
|
-
pledge: Ogmios.Lovelace;
|
|
42
|
-
cost: Ogmios.Lovelace;
|
|
43
|
-
margin: Ratio;
|
|
44
|
-
rewardAddress: AddressBech32;
|
|
45
|
-
owners: Ed25519KeyHashBech32[];
|
|
46
|
-
relays: Relay[];
|
|
47
|
-
poolMetadata?: PoolMetadata;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export class CertificateFactory {
|
|
51
|
-
readonly #stakeCredential: CSL.StakeCredential;
|
|
52
|
-
readonly #csl: CardanoSerializationLib;
|
|
53
|
-
|
|
54
|
-
constructor(csl: CardanoSerializationLib, keyManager: KeyManager) {
|
|
55
|
-
this.#csl = csl;
|
|
56
|
-
this.#stakeCredential = csl.StakeCredential.from_keyhash(keyManager.stakeKey.hash());
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
stakeKeyRegistration() {
|
|
60
|
-
return this.#csl.Certificate.new_stake_registration(this.#csl.StakeRegistration.new(this.#stakeCredential));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
stakeKeyDeregistration() {
|
|
64
|
-
return this.#csl.Certificate.new_stake_deregistration(this.#csl.StakeDeregistration.new(this.#stakeCredential));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
poolRegistration({
|
|
68
|
-
poolKeyHash,
|
|
69
|
-
vrfKeyHash,
|
|
70
|
-
pledge,
|
|
71
|
-
cost,
|
|
72
|
-
margin,
|
|
73
|
-
rewardAddress,
|
|
74
|
-
owners,
|
|
75
|
-
relays,
|
|
76
|
-
poolMetadata
|
|
77
|
-
}: PoolParameters) {
|
|
78
|
-
const cslOwners = this.#csl.Ed25519KeyHashes.new();
|
|
79
|
-
for (const owner of owners) {
|
|
80
|
-
cslOwners.add(this.#csl.Ed25519KeyHash.from_bech32(owner));
|
|
81
|
-
}
|
|
82
|
-
const cslRelays = this.#createCslRelays(relays);
|
|
83
|
-
const poolParams = this.#csl.PoolParams.new(
|
|
84
|
-
this.#csl.Ed25519KeyHash.from_bech32(poolKeyHash),
|
|
85
|
-
this.#csl.VRFKeyHash.from_bech32(vrfKeyHash),
|
|
86
|
-
this.#csl.BigNum.from_str(pledge.toString()),
|
|
87
|
-
this.#csl.BigNum.from_str(cost.toString()),
|
|
88
|
-
this.#csl.UnitInterval.new(
|
|
89
|
-
this.#csl.BigNum.from_str(margin.numerator.toString()),
|
|
90
|
-
this.#csl.BigNum.from_str(margin.denominator.toString())
|
|
91
|
-
),
|
|
92
|
-
this.#csl.RewardAddress.from_address(this.#csl.Address.from_bech32(rewardAddress))!,
|
|
93
|
-
cslOwners,
|
|
94
|
-
cslRelays,
|
|
95
|
-
poolMetadata
|
|
96
|
-
? this.#csl.PoolMetadata.new(
|
|
97
|
-
this.#csl.URL.new(poolMetadata.url),
|
|
98
|
-
this.#csl.PoolMetadataHash.from_bech32(poolMetadata.hash)
|
|
99
|
-
)
|
|
100
|
-
: undefined
|
|
101
|
-
);
|
|
102
|
-
return this.#csl.Certificate.new_pool_registration(this.#csl.PoolRegistration.new(poolParams));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
poolRetirement(poolKeyHash: Ed25519KeyHashBech32, epoch: number) {
|
|
106
|
-
return this.#csl.Certificate.new_pool_retirement(
|
|
107
|
-
this.#csl.PoolRetirement.new(this.#csl.Ed25519KeyHash.from_bech32(poolKeyHash), epoch)
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
stakeDelegation(delegatee: Ed25519KeyHashBech32) {
|
|
112
|
-
return this.#csl.Certificate.new_stake_delegation(
|
|
113
|
-
this.#csl.StakeDelegation.new(this.#stakeCredential, this.#csl.Ed25519KeyHash.from_bech32(delegatee))
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
#createCslRelays(relays: Relay[]) {
|
|
118
|
-
const cslRelays = this.#csl.Relays.new();
|
|
119
|
-
for (const relay of relays) {
|
|
120
|
-
switch (relay.relayType) {
|
|
121
|
-
case 'singlehost-addr':
|
|
122
|
-
if (relay.ipv6) {
|
|
123
|
-
throw new NotImplementedError('Parse IPv6 to byte array');
|
|
124
|
-
}
|
|
125
|
-
cslRelays.add(
|
|
126
|
-
this.#csl.Relay.new_single_host_addr(
|
|
127
|
-
this.#csl.SingleHostAddr.new(
|
|
128
|
-
relay.port,
|
|
129
|
-
relay.ipv4
|
|
130
|
-
? this.#csl.Ipv4.new(new Uint8Array(relay.ipv4.split('.').map((segment) => Number.parseInt(segment))))
|
|
131
|
-
: undefined
|
|
132
|
-
)
|
|
133
|
-
)
|
|
134
|
-
);
|
|
135
|
-
break;
|
|
136
|
-
case 'singlehost-name':
|
|
137
|
-
cslRelays.add(
|
|
138
|
-
this.#csl.Relay.new_single_host_name(
|
|
139
|
-
this.#csl.SingleHostName.new(relay.port || undefined, this.#csl.DNSRecordAorAAAA.new(relay.hostname))
|
|
140
|
-
)
|
|
141
|
-
);
|
|
142
|
-
break;
|
|
143
|
-
case 'multihost-name':
|
|
144
|
-
cslRelays.add(
|
|
145
|
-
this.#csl.Relay.new_multi_host_name(this.#csl.MultiHostName.new(this.#csl.DNSRecordSRV.new(relay.dnsName)))
|
|
146
|
-
);
|
|
147
|
-
break;
|
|
148
|
-
default:
|
|
149
|
-
throw new NotImplementedError('Relay type');
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return cslRelays;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { ImplicitCoin } from '@cardano-sdk/cip2';
|
|
2
|
-
import { BigIntMath, ProtocolParametersRequiredByWallet } from '@cardano-sdk/core';
|
|
3
|
-
import { InitializeTxProps } from './types';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Implementation is the same as in csl.get_implicit_input() and csl.get_deposit().
|
|
7
|
-
*/
|
|
8
|
-
export const computeImplicitCoin = (
|
|
9
|
-
{ stakeKeyDeposit, poolDeposit }: ProtocolParametersRequiredByWallet,
|
|
10
|
-
{ certificates, withdrawals }: InitializeTxProps
|
|
11
|
-
): ImplicitCoin => {
|
|
12
|
-
const stakeKeyDepositBigint = stakeKeyDeposit && BigInt(stakeKeyDeposit);
|
|
13
|
-
const poolDepositBigint = poolDeposit && BigInt(poolDeposit);
|
|
14
|
-
const deposit = BigIntMath.sum(
|
|
15
|
-
certificates?.map(
|
|
16
|
-
(cert) =>
|
|
17
|
-
(cert.as_stake_registration() && stakeKeyDepositBigint) ||
|
|
18
|
-
(cert.as_pool_registration() && poolDepositBigint) ||
|
|
19
|
-
0n
|
|
20
|
-
) || []
|
|
21
|
-
);
|
|
22
|
-
const withdrawalsTotal =
|
|
23
|
-
(withdrawals && BigIntMath.sum(withdrawals.map(({ quantity }) => BigInt(quantity.to_str())))) || 0n;
|
|
24
|
-
const reclaimTotal = BigIntMath.sum(
|
|
25
|
-
certificates?.map(
|
|
26
|
-
(cert) =>
|
|
27
|
-
(cert.as_stake_deregistration() && stakeKeyDepositBigint) ||
|
|
28
|
-
(cert.as_pool_retirement() && poolDepositBigint) ||
|
|
29
|
-
0n
|
|
30
|
-
) || []
|
|
31
|
-
);
|
|
32
|
-
return {
|
|
33
|
-
deposit,
|
|
34
|
-
input: withdrawalsTotal + reclaimTotal
|
|
35
|
-
};
|
|
36
|
-
};
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { SelectionResult } from '@cardano-sdk/cip2';
|
|
2
|
-
import { Transaction, CardanoSerializationLib, CSL } from '@cardano-sdk/core';
|
|
3
|
-
import { Withdrawal } from './withdrawal';
|
|
4
|
-
|
|
5
|
-
export type TxInternals = {
|
|
6
|
-
hash: CSL.TransactionHash;
|
|
7
|
-
body: CSL.TransactionBody;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type CreateTxInternalsProps = {
|
|
11
|
-
changeAddress: string;
|
|
12
|
-
inputSelection: SelectionResult['selection'];
|
|
13
|
-
validityInterval: Transaction.ValidityInterval;
|
|
14
|
-
certificates?: CSL.Certificate[];
|
|
15
|
-
withdrawals?: Withdrawal[];
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const createTransactionInternals = async (
|
|
19
|
-
csl: CardanoSerializationLib,
|
|
20
|
-
props: CreateTxInternalsProps
|
|
21
|
-
): Promise<TxInternals> => {
|
|
22
|
-
const inputs = csl.TransactionInputs.new();
|
|
23
|
-
for (const utxo of props.inputSelection.inputs) {
|
|
24
|
-
inputs.add(utxo.input());
|
|
25
|
-
}
|
|
26
|
-
const outputs = csl.TransactionOutputs.new();
|
|
27
|
-
for (const output of props.inputSelection.outputs) {
|
|
28
|
-
outputs.add(output);
|
|
29
|
-
}
|
|
30
|
-
for (const value of props.inputSelection.change) {
|
|
31
|
-
outputs.add(csl.TransactionOutput.new(csl.Address.from_bech32(props.changeAddress), value));
|
|
32
|
-
}
|
|
33
|
-
const body = csl.TransactionBody.new(
|
|
34
|
-
inputs,
|
|
35
|
-
outputs,
|
|
36
|
-
props.inputSelection.fee,
|
|
37
|
-
props.validityInterval.invalidHereafter
|
|
38
|
-
);
|
|
39
|
-
if (props.validityInterval.invalidBefore !== undefined) {
|
|
40
|
-
body.set_validity_start_interval(props.validityInterval.invalidBefore);
|
|
41
|
-
}
|
|
42
|
-
if (props.certificates?.length) {
|
|
43
|
-
const certs = csl.Certificates.new();
|
|
44
|
-
for (const cert of props.certificates) {
|
|
45
|
-
certs.add(cert);
|
|
46
|
-
}
|
|
47
|
-
body.set_certs(certs);
|
|
48
|
-
}
|
|
49
|
-
if (props.withdrawals?.length) {
|
|
50
|
-
const withdrawals = csl.Withdrawals.new();
|
|
51
|
-
for (const { address, quantity } of props.withdrawals) {
|
|
52
|
-
withdrawals.insert(address, quantity);
|
|
53
|
-
}
|
|
54
|
-
body.set_withdrawals(withdrawals);
|
|
55
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
body,
|
|
58
|
-
hash: csl.hash_transaction(body)
|
|
59
|
-
};
|
|
60
|
-
};
|
package/src/Transaction/types.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as Schema from '@cardano-ogmios/schema';
|
|
2
|
-
import { CSL, Transaction } from '@cardano-sdk/core';
|
|
3
|
-
import { Withdrawal } from './withdrawal';
|
|
4
|
-
|
|
5
|
-
export type InitializeTxProps = {
|
|
6
|
-
outputs: Set<Schema.TxOut>;
|
|
7
|
-
certificates?: CSL.Certificate[];
|
|
8
|
-
withdrawals?: Withdrawal[];
|
|
9
|
-
options?: {
|
|
10
|
-
validityInterval?: Transaction.ValidityInterval;
|
|
11
|
-
};
|
|
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/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
|
-
});
|