@atomiqlabs/base 10.0.0-dev.2 → 10.0.0-dev.4
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 -201
- package/dist/btc/BitcoinNetwork.d.ts +6 -6
- package/dist/btc/BitcoinNetwork.js +10 -10
- package/dist/btc/rpc/BitcoinRpc.d.ts +68 -68
- package/dist/btc/rpc/BitcoinRpc.js +2 -2
- package/dist/btcrelay/BtcRelay.d.ts +61 -61
- package/dist/btcrelay/BtcRelay.js +2 -2
- package/dist/btcrelay/synchronizer/RelaySynchronizer.d.ts +18 -18
- package/dist/btcrelay/synchronizer/RelaySynchronizer.js +2 -2
- package/dist/btcrelay/types/BtcBlock.d.ts +13 -13
- package/dist/btcrelay/types/BtcBlock.js +2 -2
- package/dist/btcrelay/types/BtcHeader.d.ts +10 -10
- package/dist/btcrelay/types/BtcHeader.js +2 -2
- package/dist/btcrelay/types/BtcStoredHeader.d.ts +11 -11
- package/dist/btcrelay/types/BtcStoredHeader.js +2 -2
- package/dist/btcrelay/utils/StatePredictorUtils.d.ts +11 -11
- package/dist/btcrelay/utils/StatePredictorUtils.js +80 -80
- package/dist/chains/ChainData.d.ts +31 -31
- package/dist/chains/ChainData.js +2 -2
- package/dist/chains/ChainInterface.d.ts +110 -110
- package/dist/chains/ChainInterface.js +2 -2
- package/dist/chains/ChainType.d.ts +23 -23
- package/dist/chains/ChainType.js +2 -2
- package/dist/errors/CannotInitializeATAError.d.ts +3 -3
- package/dist/errors/CannotInitializeATAError.js +11 -11
- package/dist/errors/SignatureVerificationError.d.ts +3 -3
- package/dist/errors/SignatureVerificationError.js +11 -11
- package/dist/errors/SwapDataVerificationError.d.ts +3 -3
- package/dist/errors/SwapDataVerificationError.js +11 -11
- package/dist/events/ChainEvents.d.ts +9 -9
- package/dist/events/ChainEvents.js +2 -2
- package/dist/events/types/ChainEvent.d.ts +7 -7
- package/dist/events/types/ChainEvent.js +6 -6
- package/dist/events/types/spv_vault/SpvVaultClaimEvent.d.ts +12 -12
- package/dist/events/types/spv_vault/SpvVaultClaimEvent.js +18 -18
- package/dist/events/types/spv_vault/SpvVaultCloseEvent.d.ts +7 -7
- package/dist/events/types/spv_vault/SpvVaultCloseEvent.js +13 -13
- package/dist/events/types/spv_vault/SpvVaultDepositEvent.d.ts +7 -7
- package/dist/events/types/spv_vault/SpvVaultDepositEvent.js +13 -13
- package/dist/events/types/spv_vault/SpvVaultEvent.d.ts +15 -15
- package/dist/events/types/spv_vault/SpvVaultEvent.js +20 -20
- package/dist/events/types/spv_vault/SpvVaultFrontEvent.d.ts +10 -10
- package/dist/events/types/spv_vault/SpvVaultFrontEvent.js +16 -16
- package/dist/events/types/spv_vault/SpvVaultOpenEvent.d.ts +7 -7
- package/dist/events/types/spv_vault/SpvVaultOpenEvent.js +13 -13
- package/dist/events/types/swap/ClaimEvent.d.ts +7 -7
- package/dist/events/types/swap/ClaimEvent.js +11 -11
- package/dist/events/types/swap/InitializeEvent.d.ts +9 -9
- package/dist/events/types/swap/InitializeEvent.js +12 -12
- package/dist/events/types/swap/RefundEvent.d.ts +5 -5
- package/dist/events/types/swap/RefundEvent.js +7 -7
- package/dist/events/types/swap/SwapEvent.d.ts +12 -12
- package/dist/events/types/swap/SwapEvent.js +17 -17
- package/dist/index.d.ts +41 -38
- package/dist/index.js +57 -54
- package/dist/lockable/Lockable.d.ts +6 -6
- package/dist/lockable/Lockable.js +28 -28
- package/dist/messaging/EventMessaging.d.ts +8 -0
- package/dist/messaging/EventMessaging.js +2 -0
- package/dist/messaging/Messenger.d.ts +8 -0
- package/dist/messaging/Messenger.js +2 -0
- package/dist/messaging/messages/Message.d.ts +11 -0
- package/dist/messaging/messages/Message.js +21 -0
- package/dist/messaging/messages/SwapClaimWitnessMessage.d.ts +13 -0
- package/dist/messaging/messages/SwapClaimWitnessMessage.js +27 -0
- package/dist/spv_swap/SpvVaultContract.d.ts +199 -199
- package/dist/spv_swap/SpvVaultContract.js +2 -2
- package/dist/spv_swap/SpvVaultData.d.ts +35 -35
- package/dist/spv_swap/SpvVaultData.js +37 -37
- package/dist/spv_swap/SpvWithdrawalState.d.ts +31 -31
- package/dist/spv_swap/SpvWithdrawalState.js +10 -10
- package/dist/spv_swap/SpvWithdrawalTransactionData.d.ts +43 -43
- package/dist/spv_swap/SpvWithdrawalTransactionData.js +143 -143
- package/dist/storage/IStorageManager.d.ts +15 -15
- package/dist/storage/IStorageManager.js +2 -2
- package/dist/storage/StorageObject.d.ts +3 -3
- package/dist/storage/StorageObject.js +2 -2
- package/dist/swaps/ChainSwapType.d.ts +6 -6
- package/dist/swaps/ChainSwapType.js +10 -10
- package/dist/swaps/SwapCommitState.d.ts +38 -38
- package/dist/swaps/SwapCommitState.js +11 -11
- package/dist/swaps/SwapContract.d.ts +467 -467
- package/dist/swaps/SwapContract.js +2 -2
- package/dist/swaps/SwapData.d.ts +36 -36
- package/dist/swaps/SwapData.js +14 -14
- package/dist/utils/BigIntBufferUtils.d.ts +6 -6
- package/dist/utils/BigIntBufferUtils.js +31 -31
- package/package.json +31 -31
- package/src/btc/BitcoinNetwork.ts +6 -6
- package/src/btc/rpc/BitcoinRpc.ts +77 -77
- package/src/btcrelay/BtcRelay.ts +70 -70
- package/src/btcrelay/synchronizer/RelaySynchronizer.ts +17 -17
- package/src/btcrelay/types/BtcBlock.ts +15 -15
- package/src/btcrelay/types/BtcHeader.ts +11 -11
- package/src/btcrelay/types/BtcStoredHeader.ts +12 -12
- package/src/btcrelay/utils/StatePredictorUtils.ts +108 -108
- package/src/chains/ChainData.ts +40 -40
- package/src/chains/ChainInterface.ts +132 -132
- package/src/chains/ChainType.ts +38 -38
- package/src/errors/CannotInitializeATAError.ts +11 -11
- package/src/errors/SignatureVerificationError.ts +11 -11
- package/src/errors/SwapDataVerificationError.ts +11 -11
- package/src/events/ChainEvents.ts +13 -13
- package/src/events/types/ChainEvent.ts +10 -10
- package/src/events/types/spv_vault/SpvVaultClaimEvent.ts +31 -31
- package/src/events/types/spv_vault/SpvVaultCloseEvent.ts +17 -17
- package/src/events/types/spv_vault/SpvVaultDepositEvent.ts +17 -17
- package/src/events/types/spv_vault/SpvVaultEvent.ts +25 -25
- package/src/events/types/spv_vault/SpvVaultFrontEvent.ts +27 -27
- package/src/events/types/spv_vault/SpvVaultOpenEvent.ts +16 -16
- package/src/events/types/swap/ClaimEvent.ts +15 -15
- package/src/events/types/swap/InitializeEvent.ts +18 -18
- package/src/events/types/swap/RefundEvent.ts +6 -6
- package/src/events/types/swap/SwapEvent.ts +21 -21
- package/src/index.ts +50 -46
- package/src/lockable/Lockable.ts +30 -30
- package/src/messaging/Messenger.ts +11 -0
- package/src/messaging/messages/Message.ts +25 -0
- package/src/messaging/messages/SwapClaimWitnessMessage.ts +33 -0
- package/src/spv_swap/SpvVaultContract.ts +230 -230
- package/src/spv_swap/SpvVaultData.ts +70 -70
- package/src/spv_swap/SpvWithdrawalState.ts +40 -40
- package/src/spv_swap/SpvWithdrawalTransactionData.ts +169 -169
- package/src/storage/IStorageManager.ts +16 -16
- package/src/storage/StorageObject.ts +6 -6
- package/src/swaps/ChainSwapType.ts +6 -6
- package/src/swaps/SwapCommitState.ts +39 -39
- package/src/swaps/SwapContract.ts +556 -556
- package/src/swaps/SwapData.ts +65 -65
- package/src/utils/BigIntBufferUtils.ts +31 -31
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
import {StorageObject} from "../storage/StorageObject";
|
|
2
|
-
import {SpvWithdrawalTransactionData} from "./SpvWithdrawalTransactionData";
|
|
3
|
-
import {SpvVaultClaimEvent} from "../events/types/spv_vault/SpvVaultClaimEvent";
|
|
4
|
-
import {SpvVaultCloseEvent} from "../events/types/spv_vault/SpvVaultCloseEvent";
|
|
5
|
-
import {SpvVaultOpenEvent} from "../events/types/spv_vault/SpvVaultOpenEvent";
|
|
6
|
-
import {SpvVaultDepositEvent} from "../events/types/spv_vault/SpvVaultDepositEvent";
|
|
7
|
-
|
|
8
|
-
export type SpvVaultTokenBalance = SpvVaultTokenData & {
|
|
9
|
-
rawAmount: bigint,
|
|
10
|
-
scaledAmount: bigint
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type SpvVaultTokenData = {
|
|
14
|
-
token: string,
|
|
15
|
-
multiplier: bigint
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export abstract class SpvVaultData<T extends SpvWithdrawalTransactionData = SpvWithdrawalTransactionData> implements StorageObject {
|
|
19
|
-
|
|
20
|
-
static deserializers: {
|
|
21
|
-
[type: string]: new (serialized: any) => any,
|
|
22
|
-
} = {};
|
|
23
|
-
|
|
24
|
-
static deserialize<T extends SpvVaultData>(data: any): T {
|
|
25
|
-
if (SpvVaultData.deserializers[data.type] != null) {
|
|
26
|
-
return new SpvVaultData.deserializers[data.type](data) as unknown as T;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
abstract serialize(): any;
|
|
31
|
-
|
|
32
|
-
abstract getOwner(): string;
|
|
33
|
-
abstract getVaultId(): bigint;
|
|
34
|
-
abstract getTokenData(): SpvVaultTokenData[];
|
|
35
|
-
|
|
36
|
-
abstract getBalances(): SpvVaultTokenBalance[];
|
|
37
|
-
abstract getUtxo(): string;
|
|
38
|
-
abstract getConfirmations(): number;
|
|
39
|
-
abstract getWithdrawalCount(): number;
|
|
40
|
-
abstract getDepositCount(): number;
|
|
41
|
-
abstract isOpened(): boolean;
|
|
42
|
-
|
|
43
|
-
abstract updateState(withdrawalTxOrEvent: T | SpvVaultClaimEvent | SpvVaultCloseEvent | SpvVaultOpenEvent | SpvVaultDepositEvent): void;
|
|
44
|
-
|
|
45
|
-
calculateStateAfter(priorWithdrawalTxs: T[]): {withdrawalCount: number, balances: SpvVaultTokenBalance[]} {
|
|
46
|
-
const balances = [...this.getBalances()];
|
|
47
|
-
let withdrawalCount = this.getWithdrawalCount();
|
|
48
|
-
let utxo = this.getUtxo();
|
|
49
|
-
for(let withdrawalTx of priorWithdrawalTxs) {
|
|
50
|
-
if(withdrawalTx.getSpentVaultUtxo()!==utxo) throw new Error("Invalid transaction, doesn't spend prior vault UTXO!");
|
|
51
|
-
withdrawalTx.getTotalOutput().forEach((value, i) => {
|
|
52
|
-
if(balances[i]==null) throw new Error("Tried to withdraw non-existing token!");
|
|
53
|
-
balances[i].rawAmount -= value;
|
|
54
|
-
if(balances[i].rawAmount < 0n) throw new Error("Prior transaction withdrew more than available in vault");
|
|
55
|
-
});
|
|
56
|
-
utxo = withdrawalTx.getCreatedVaultUtxo();
|
|
57
|
-
withdrawalCount++;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
balances.forEach(balance => {
|
|
61
|
-
balance.scaledAmount = balance.rawAmount * balance.multiplier;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
withdrawalCount,
|
|
66
|
-
balances
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
}
|
|
1
|
+
import {StorageObject} from "../storage/StorageObject";
|
|
2
|
+
import {SpvWithdrawalTransactionData} from "./SpvWithdrawalTransactionData";
|
|
3
|
+
import {SpvVaultClaimEvent} from "../events/types/spv_vault/SpvVaultClaimEvent";
|
|
4
|
+
import {SpvVaultCloseEvent} from "../events/types/spv_vault/SpvVaultCloseEvent";
|
|
5
|
+
import {SpvVaultOpenEvent} from "../events/types/spv_vault/SpvVaultOpenEvent";
|
|
6
|
+
import {SpvVaultDepositEvent} from "../events/types/spv_vault/SpvVaultDepositEvent";
|
|
7
|
+
|
|
8
|
+
export type SpvVaultTokenBalance = SpvVaultTokenData & {
|
|
9
|
+
rawAmount: bigint,
|
|
10
|
+
scaledAmount: bigint
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SpvVaultTokenData = {
|
|
14
|
+
token: string,
|
|
15
|
+
multiplier: bigint
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export abstract class SpvVaultData<T extends SpvWithdrawalTransactionData = SpvWithdrawalTransactionData> implements StorageObject {
|
|
19
|
+
|
|
20
|
+
static deserializers: {
|
|
21
|
+
[type: string]: new (serialized: any) => any,
|
|
22
|
+
} = {};
|
|
23
|
+
|
|
24
|
+
static deserialize<T extends SpvVaultData>(data: any): T {
|
|
25
|
+
if (SpvVaultData.deserializers[data.type] != null) {
|
|
26
|
+
return new SpvVaultData.deserializers[data.type](data) as unknown as T;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
abstract serialize(): any;
|
|
31
|
+
|
|
32
|
+
abstract getOwner(): string;
|
|
33
|
+
abstract getVaultId(): bigint;
|
|
34
|
+
abstract getTokenData(): SpvVaultTokenData[];
|
|
35
|
+
|
|
36
|
+
abstract getBalances(): SpvVaultTokenBalance[];
|
|
37
|
+
abstract getUtxo(): string;
|
|
38
|
+
abstract getConfirmations(): number;
|
|
39
|
+
abstract getWithdrawalCount(): number;
|
|
40
|
+
abstract getDepositCount(): number;
|
|
41
|
+
abstract isOpened(): boolean;
|
|
42
|
+
|
|
43
|
+
abstract updateState(withdrawalTxOrEvent: T | SpvVaultClaimEvent | SpvVaultCloseEvent | SpvVaultOpenEvent | SpvVaultDepositEvent): void;
|
|
44
|
+
|
|
45
|
+
calculateStateAfter(priorWithdrawalTxs: T[]): {withdrawalCount: number, balances: SpvVaultTokenBalance[]} {
|
|
46
|
+
const balances = [...this.getBalances()];
|
|
47
|
+
let withdrawalCount = this.getWithdrawalCount();
|
|
48
|
+
let utxo = this.getUtxo();
|
|
49
|
+
for(let withdrawalTx of priorWithdrawalTxs) {
|
|
50
|
+
if(withdrawalTx.getSpentVaultUtxo()!==utxo) throw new Error("Invalid transaction, doesn't spend prior vault UTXO!");
|
|
51
|
+
withdrawalTx.getTotalOutput().forEach((value, i) => {
|
|
52
|
+
if(balances[i]==null) throw new Error("Tried to withdraw non-existing token!");
|
|
53
|
+
balances[i].rawAmount -= value;
|
|
54
|
+
if(balances[i].rawAmount < 0n) throw new Error("Prior transaction withdrew more than available in vault");
|
|
55
|
+
});
|
|
56
|
+
utxo = withdrawalTx.getCreatedVaultUtxo();
|
|
57
|
+
withdrawalCount++;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
balances.forEach(balance => {
|
|
61
|
+
balance.scaledAmount = balance.rawAmount * balance.multiplier;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
withdrawalCount,
|
|
66
|
+
balances
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
export enum SpvWithdrawalStateType {
|
|
3
|
-
CLOSED = -1,
|
|
4
|
-
NOT_FOUND = 0,
|
|
5
|
-
CLAIMED = 1,
|
|
6
|
-
FRONTED = 2
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export type SpvWithdrawalNotFoundState = {
|
|
10
|
-
type: SpvWithdrawalStateType.NOT_FOUND
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
type SpvWithdrawalStateCommon = {
|
|
14
|
-
txId: string,
|
|
15
|
-
owner: string,
|
|
16
|
-
vaultId: bigint,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type SpvWithdrawalClaimedState = {
|
|
20
|
-
type: SpvWithdrawalStateType.CLAIMED,
|
|
21
|
-
recipient: string,
|
|
22
|
-
claimer: string,
|
|
23
|
-
fronter: string
|
|
24
|
-
} & SpvWithdrawalStateCommon;
|
|
25
|
-
|
|
26
|
-
export type SpvWithdrawalFrontedState = {
|
|
27
|
-
type: SpvWithdrawalStateType.FRONTED,
|
|
28
|
-
recipient: string,
|
|
29
|
-
fronter: string
|
|
30
|
-
} & SpvWithdrawalStateCommon;
|
|
31
|
-
|
|
32
|
-
export type SpvWithdrawalClosedState = {
|
|
33
|
-
type: SpvWithdrawalStateType.CLOSED,
|
|
34
|
-
error: string
|
|
35
|
-
} & SpvWithdrawalStateCommon;
|
|
36
|
-
|
|
37
|
-
export type SpvWithdrawalState = SpvWithdrawalNotFoundState |
|
|
38
|
-
SpvWithdrawalClaimedState |
|
|
39
|
-
SpvWithdrawalFrontedState |
|
|
40
|
-
SpvWithdrawalClosedState;
|
|
1
|
+
|
|
2
|
+
export enum SpvWithdrawalStateType {
|
|
3
|
+
CLOSED = -1,
|
|
4
|
+
NOT_FOUND = 0,
|
|
5
|
+
CLAIMED = 1,
|
|
6
|
+
FRONTED = 2
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type SpvWithdrawalNotFoundState = {
|
|
10
|
+
type: SpvWithdrawalStateType.NOT_FOUND
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type SpvWithdrawalStateCommon = {
|
|
14
|
+
txId: string,
|
|
15
|
+
owner: string,
|
|
16
|
+
vaultId: bigint,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type SpvWithdrawalClaimedState = {
|
|
20
|
+
type: SpvWithdrawalStateType.CLAIMED,
|
|
21
|
+
recipient: string,
|
|
22
|
+
claimer: string,
|
|
23
|
+
fronter: string
|
|
24
|
+
} & SpvWithdrawalStateCommon;
|
|
25
|
+
|
|
26
|
+
export type SpvWithdrawalFrontedState = {
|
|
27
|
+
type: SpvWithdrawalStateType.FRONTED,
|
|
28
|
+
recipient: string,
|
|
29
|
+
fronter: string
|
|
30
|
+
} & SpvWithdrawalStateCommon;
|
|
31
|
+
|
|
32
|
+
export type SpvWithdrawalClosedState = {
|
|
33
|
+
type: SpvWithdrawalStateType.CLOSED,
|
|
34
|
+
error: string
|
|
35
|
+
} & SpvWithdrawalStateCommon;
|
|
36
|
+
|
|
37
|
+
export type SpvWithdrawalState = SpvWithdrawalNotFoundState |
|
|
38
|
+
SpvWithdrawalClaimedState |
|
|
39
|
+
SpvWithdrawalFrontedState |
|
|
40
|
+
SpvWithdrawalClosedState;
|
|
@@ -1,170 +1,170 @@
|
|
|
1
|
-
import {BtcTx} from "../btc/rpc/BitcoinRpc";
|
|
2
|
-
import {Buffer} from "buffer";
|
|
3
|
-
import {StorageObject} from "../storage/StorageObject";
|
|
4
|
-
|
|
5
|
-
export type ExecutionData = {
|
|
6
|
-
executionHash: string,
|
|
7
|
-
executionExpiry: number
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export abstract class SpvWithdrawalTransactionData implements StorageObject {
|
|
11
|
-
|
|
12
|
-
static deserializers: {
|
|
13
|
-
[type: string]: new (serialized: any) => any,
|
|
14
|
-
} = {};
|
|
15
|
-
|
|
16
|
-
static deserialize<T extends SpvWithdrawalTransactionData>(data: any): T {
|
|
17
|
-
if (SpvWithdrawalTransactionData.deserializers[data.type] != null) {
|
|
18
|
-
return new SpvWithdrawalTransactionData.deserializers[data.type](data) as unknown as T;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
protected abstract fromOpReturnData(data: Buffer): {recipient: string, rawAmounts: bigint[], executionHash: string};
|
|
23
|
-
|
|
24
|
-
readonly recipient: string;
|
|
25
|
-
readonly rawAmounts: bigint[];
|
|
26
|
-
|
|
27
|
-
readonly callerFeeRate: bigint;
|
|
28
|
-
readonly executionFeeRate: bigint;
|
|
29
|
-
readonly frontingFeeRate: bigint;
|
|
30
|
-
|
|
31
|
-
readonly executionHash: string;
|
|
32
|
-
readonly executionExpiry: number;
|
|
33
|
-
|
|
34
|
-
readonly btcTx: BtcTx;
|
|
35
|
-
|
|
36
|
-
constructor(btcTx: BtcTx) {
|
|
37
|
-
if(btcTx.ins.length<2) throw new Error("Need at least 2 inputs");
|
|
38
|
-
if(btcTx.outs.length<2) throw new Error("Need at least 2 outputs");
|
|
39
|
-
|
|
40
|
-
const nSequence0 = BigInt(btcTx.ins[0].sequence);
|
|
41
|
-
const nSequence1 = BigInt(btcTx.ins[1].sequence);
|
|
42
|
-
|
|
43
|
-
if((nSequence0 & 0x80000000n) != 0x80000000n) throw new Error("nSequence0 high bit not set!");
|
|
44
|
-
if((nSequence1 & 0x80000000n) != 0x80000000n) throw new Error("nSequence0 high bit not set!");
|
|
45
|
-
const callerFeeRate: bigint = nSequence0 & 0xFFFFFn;
|
|
46
|
-
const executionFeeRate: bigint = nSequence1 & 0xFFFFFn;
|
|
47
|
-
const frontingFeeRate: bigint = ((nSequence0 >> 10n) & 0b1111_1111_1100_0000_0000n) | ((nSequence1 >> 20n) & 0b11_1111_1111n);
|
|
48
|
-
|
|
49
|
-
const executionExpiry = btcTx.locktime + 1_000_000_000;
|
|
50
|
-
if(executionExpiry >= Math.pow(2, 32)) throw new Error("Execution expiry overflow");
|
|
51
|
-
|
|
52
|
-
const opReturnOutput = btcTx.outs[1];
|
|
53
|
-
//Parse script
|
|
54
|
-
const opReturnData = Buffer.from(opReturnOutput.scriptPubKey.hex, "hex");
|
|
55
|
-
if(opReturnData.length===0) throw new Error("Output 1 empty script");
|
|
56
|
-
if(opReturnData.at(0)!==0x6a) throw new Error("Output 1 is not OP_RETURN");
|
|
57
|
-
if(opReturnData.at(1)===0) throw new Error("Output 1 OP_RETURN followed by OP_0");
|
|
58
|
-
let data: Buffer;
|
|
59
|
-
if(opReturnData.at(1) === 0x4c) { //OP_PUSHDATA1
|
|
60
|
-
const dataLength = opReturnData.at(2);
|
|
61
|
-
data = opReturnData.subarray(3, 3+dataLength);
|
|
62
|
-
if(data.length !== dataLength) throw new Error("Output 1 OP_RETURN data length mismatch!");
|
|
63
|
-
} else if(opReturnData.at(1) <= 0x4b) { //OP_PUSH<length>
|
|
64
|
-
const dataLength = opReturnData.at(1);
|
|
65
|
-
data = opReturnData.subarray(2, 2+dataLength);
|
|
66
|
-
if(data.length !== dataLength) throw new Error("Output 1 OP_RETURN data length mismatch!");
|
|
67
|
-
} else {
|
|
68
|
-
throw new Error("Output 1 invalid push opcode");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
//Parse OP_RETURN data
|
|
72
|
-
const res = this.fromOpReturnData(data);
|
|
73
|
-
|
|
74
|
-
this.recipient = res.recipient;
|
|
75
|
-
this.rawAmounts = res.rawAmounts;
|
|
76
|
-
|
|
77
|
-
this.callerFeeRate = callerFeeRate;
|
|
78
|
-
this.frontingFeeRate = frontingFeeRate;
|
|
79
|
-
this.executionFeeRate = executionFeeRate;
|
|
80
|
-
|
|
81
|
-
this.executionHash = res.executionHash;
|
|
82
|
-
this.executionExpiry = executionExpiry;
|
|
83
|
-
|
|
84
|
-
this.btcTx = btcTx;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
serialize(): any {
|
|
88
|
-
return this.btcTx;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
getRecipient(): string {
|
|
92
|
-
return this.recipient;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
abstract isRecipient(address: string): boolean;
|
|
96
|
-
|
|
97
|
-
abstract getFrontingId(): string;
|
|
98
|
-
|
|
99
|
-
getOutputWithoutFees(): bigint[] {
|
|
100
|
-
return this.rawAmounts;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
getCallerFee(): bigint[] {
|
|
104
|
-
return this.rawAmounts.map(val => val * this.callerFeeRate / 100_000n);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
getFrontingFee(): bigint[] {
|
|
108
|
-
return this.rawAmounts.map(val => val * this.frontingFeeRate / 100_000n);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
getExecutionFee(): bigint[] {
|
|
112
|
-
return [this.rawAmounts[0] * this.executionFeeRate / 100_000n];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
getTotalOutput(): bigint[] {
|
|
116
|
-
const amounts = [...this.getOutputWithoutFees()];
|
|
117
|
-
const callerFee = this.getCallerFee();
|
|
118
|
-
if(callerFee!=null) callerFee.forEach((fee, i) => {
|
|
119
|
-
if(fee==null || fee===0n) return;
|
|
120
|
-
if(amounts[i]==null) throw new Error("Caller fee token out of bounds");
|
|
121
|
-
amounts[i] += fee;
|
|
122
|
-
});
|
|
123
|
-
const frontingFee = this.getFrontingFee();
|
|
124
|
-
if(frontingFee!=null) frontingFee.forEach((fee, i) => {
|
|
125
|
-
if(fee==null || fee===0n) return;
|
|
126
|
-
if(amounts[i]==null) throw new Error("Fronting fee token out of bounds");
|
|
127
|
-
amounts[i] += fee;
|
|
128
|
-
});
|
|
129
|
-
const executionFee = this.getExecutionFee();
|
|
130
|
-
if(executionFee!=null) executionFee.forEach((fee, i) => {
|
|
131
|
-
if(fee==null || fee===0n) return;
|
|
132
|
-
if(amounts[i]==null) throw new Error("Execution fee token out of bounds");
|
|
133
|
-
amounts[i] += fee;
|
|
134
|
-
});
|
|
135
|
-
amounts.forEach((val, index) => {
|
|
136
|
-
if(val >= 2n**64n) throw new Error("Token "+index+" amount out of bounds");
|
|
137
|
-
})
|
|
138
|
-
return amounts;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
getExecutionData(): ExecutionData | null {
|
|
142
|
-
if(this.executionHash==null) return null;
|
|
143
|
-
return {
|
|
144
|
-
executionHash: this.executionHash,
|
|
145
|
-
executionExpiry: this.executionExpiry
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
getTxId(): string {
|
|
150
|
-
return this.btcTx.txid;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
getSpentVaultUtxo(): string {
|
|
154
|
-
const in0 = this.btcTx.ins[0];
|
|
155
|
-
return in0.txid+":"+in0.vout;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
getCreatedVaultUtxo(): string {
|
|
159
|
-
return this.getTxId()+":0";
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
getNewVaultScript(): Buffer {
|
|
163
|
-
return Buffer.from(this.btcTx.outs[0].scriptPubKey.hex, "hex");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
getNewVaultBtcAmount(): number {
|
|
167
|
-
return this.btcTx.outs[0].value;
|
|
168
|
-
}
|
|
169
|
-
|
|
1
|
+
import {BtcTx} from "../btc/rpc/BitcoinRpc";
|
|
2
|
+
import {Buffer} from "buffer";
|
|
3
|
+
import {StorageObject} from "../storage/StorageObject";
|
|
4
|
+
|
|
5
|
+
export type ExecutionData = {
|
|
6
|
+
executionHash: string,
|
|
7
|
+
executionExpiry: number
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export abstract class SpvWithdrawalTransactionData implements StorageObject {
|
|
11
|
+
|
|
12
|
+
static deserializers: {
|
|
13
|
+
[type: string]: new (serialized: any) => any,
|
|
14
|
+
} = {};
|
|
15
|
+
|
|
16
|
+
static deserialize<T extends SpvWithdrawalTransactionData>(data: any): T {
|
|
17
|
+
if (SpvWithdrawalTransactionData.deserializers[data.type] != null) {
|
|
18
|
+
return new SpvWithdrawalTransactionData.deserializers[data.type](data) as unknown as T;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected abstract fromOpReturnData(data: Buffer): {recipient: string, rawAmounts: bigint[], executionHash: string};
|
|
23
|
+
|
|
24
|
+
readonly recipient: string;
|
|
25
|
+
readonly rawAmounts: bigint[];
|
|
26
|
+
|
|
27
|
+
readonly callerFeeRate: bigint;
|
|
28
|
+
readonly executionFeeRate: bigint;
|
|
29
|
+
readonly frontingFeeRate: bigint;
|
|
30
|
+
|
|
31
|
+
readonly executionHash: string;
|
|
32
|
+
readonly executionExpiry: number;
|
|
33
|
+
|
|
34
|
+
readonly btcTx: BtcTx;
|
|
35
|
+
|
|
36
|
+
constructor(btcTx: BtcTx) {
|
|
37
|
+
if(btcTx.ins.length<2) throw new Error("Need at least 2 inputs");
|
|
38
|
+
if(btcTx.outs.length<2) throw new Error("Need at least 2 outputs");
|
|
39
|
+
|
|
40
|
+
const nSequence0 = BigInt(btcTx.ins[0].sequence);
|
|
41
|
+
const nSequence1 = BigInt(btcTx.ins[1].sequence);
|
|
42
|
+
|
|
43
|
+
if((nSequence0 & 0x80000000n) != 0x80000000n) throw new Error("nSequence0 high bit not set!");
|
|
44
|
+
if((nSequence1 & 0x80000000n) != 0x80000000n) throw new Error("nSequence0 high bit not set!");
|
|
45
|
+
const callerFeeRate: bigint = nSequence0 & 0xFFFFFn;
|
|
46
|
+
const executionFeeRate: bigint = nSequence1 & 0xFFFFFn;
|
|
47
|
+
const frontingFeeRate: bigint = ((nSequence0 >> 10n) & 0b1111_1111_1100_0000_0000n) | ((nSequence1 >> 20n) & 0b11_1111_1111n);
|
|
48
|
+
|
|
49
|
+
const executionExpiry = btcTx.locktime + 1_000_000_000;
|
|
50
|
+
if(executionExpiry >= Math.pow(2, 32)) throw new Error("Execution expiry overflow");
|
|
51
|
+
|
|
52
|
+
const opReturnOutput = btcTx.outs[1];
|
|
53
|
+
//Parse script
|
|
54
|
+
const opReturnData = Buffer.from(opReturnOutput.scriptPubKey.hex, "hex");
|
|
55
|
+
if(opReturnData.length===0) throw new Error("Output 1 empty script");
|
|
56
|
+
if(opReturnData.at(0)!==0x6a) throw new Error("Output 1 is not OP_RETURN");
|
|
57
|
+
if(opReturnData.at(1)===0) throw new Error("Output 1 OP_RETURN followed by OP_0");
|
|
58
|
+
let data: Buffer;
|
|
59
|
+
if(opReturnData.at(1) === 0x4c) { //OP_PUSHDATA1
|
|
60
|
+
const dataLength = opReturnData.at(2);
|
|
61
|
+
data = opReturnData.subarray(3, 3+dataLength);
|
|
62
|
+
if(data.length !== dataLength) throw new Error("Output 1 OP_RETURN data length mismatch!");
|
|
63
|
+
} else if(opReturnData.at(1) <= 0x4b) { //OP_PUSH<length>
|
|
64
|
+
const dataLength = opReturnData.at(1);
|
|
65
|
+
data = opReturnData.subarray(2, 2+dataLength);
|
|
66
|
+
if(data.length !== dataLength) throw new Error("Output 1 OP_RETURN data length mismatch!");
|
|
67
|
+
} else {
|
|
68
|
+
throw new Error("Output 1 invalid push opcode");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//Parse OP_RETURN data
|
|
72
|
+
const res = this.fromOpReturnData(data);
|
|
73
|
+
|
|
74
|
+
this.recipient = res.recipient;
|
|
75
|
+
this.rawAmounts = res.rawAmounts;
|
|
76
|
+
|
|
77
|
+
this.callerFeeRate = callerFeeRate;
|
|
78
|
+
this.frontingFeeRate = frontingFeeRate;
|
|
79
|
+
this.executionFeeRate = executionFeeRate;
|
|
80
|
+
|
|
81
|
+
this.executionHash = res.executionHash;
|
|
82
|
+
this.executionExpiry = executionExpiry;
|
|
83
|
+
|
|
84
|
+
this.btcTx = btcTx;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
serialize(): any {
|
|
88
|
+
return this.btcTx;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getRecipient(): string {
|
|
92
|
+
return this.recipient;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
abstract isRecipient(address: string): boolean;
|
|
96
|
+
|
|
97
|
+
abstract getFrontingId(): string;
|
|
98
|
+
|
|
99
|
+
getOutputWithoutFees(): bigint[] {
|
|
100
|
+
return this.rawAmounts;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getCallerFee(): bigint[] {
|
|
104
|
+
return this.rawAmounts.map(val => val * this.callerFeeRate / 100_000n);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
getFrontingFee(): bigint[] {
|
|
108
|
+
return this.rawAmounts.map(val => val * this.frontingFeeRate / 100_000n);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getExecutionFee(): bigint[] {
|
|
112
|
+
return [this.rawAmounts[0] * this.executionFeeRate / 100_000n];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getTotalOutput(): bigint[] {
|
|
116
|
+
const amounts = [...this.getOutputWithoutFees()];
|
|
117
|
+
const callerFee = this.getCallerFee();
|
|
118
|
+
if(callerFee!=null) callerFee.forEach((fee, i) => {
|
|
119
|
+
if(fee==null || fee===0n) return;
|
|
120
|
+
if(amounts[i]==null) throw new Error("Caller fee token out of bounds");
|
|
121
|
+
amounts[i] += fee;
|
|
122
|
+
});
|
|
123
|
+
const frontingFee = this.getFrontingFee();
|
|
124
|
+
if(frontingFee!=null) frontingFee.forEach((fee, i) => {
|
|
125
|
+
if(fee==null || fee===0n) return;
|
|
126
|
+
if(amounts[i]==null) throw new Error("Fronting fee token out of bounds");
|
|
127
|
+
amounts[i] += fee;
|
|
128
|
+
});
|
|
129
|
+
const executionFee = this.getExecutionFee();
|
|
130
|
+
if(executionFee!=null) executionFee.forEach((fee, i) => {
|
|
131
|
+
if(fee==null || fee===0n) return;
|
|
132
|
+
if(amounts[i]==null) throw new Error("Execution fee token out of bounds");
|
|
133
|
+
amounts[i] += fee;
|
|
134
|
+
});
|
|
135
|
+
amounts.forEach((val, index) => {
|
|
136
|
+
if(val >= 2n**64n) throw new Error("Token "+index+" amount out of bounds");
|
|
137
|
+
})
|
|
138
|
+
return amounts;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getExecutionData(): ExecutionData | null {
|
|
142
|
+
if(this.executionHash==null) return null;
|
|
143
|
+
return {
|
|
144
|
+
executionHash: this.executionHash,
|
|
145
|
+
executionExpiry: this.executionExpiry
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
getTxId(): string {
|
|
150
|
+
return this.btcTx.txid;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
getSpentVaultUtxo(): string {
|
|
154
|
+
const in0 = this.btcTx.ins[0];
|
|
155
|
+
return in0.txid+":"+in0.vout;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
getCreatedVaultUtxo(): string {
|
|
159
|
+
return this.getTxId()+":0";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getNewVaultScript(): Buffer {
|
|
163
|
+
return Buffer.from(this.btcTx.outs[0].scriptPubKey.hex, "hex");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
getNewVaultBtcAmount(): number {
|
|
167
|
+
return this.btcTx.outs[0].value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
170
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {StorageObject} from "./StorageObject";
|
|
2
|
-
|
|
3
|
-
export interface IStorageManager<T extends StorageObject> {
|
|
4
|
-
|
|
5
|
-
data: {
|
|
6
|
-
[key: string]: T
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
init(): Promise<void>;
|
|
10
|
-
saveData(hash: string, object: T): Promise<void>;
|
|
11
|
-
removeData(hash: string): Promise<void>;
|
|
12
|
-
loadData(type: new(data: any) => T): Promise<T[]>;
|
|
13
|
-
|
|
14
|
-
removeDataArr?(keys: string[]): Promise<void>;
|
|
15
|
-
saveDataArr?(values: {id: string, object: T}[]): Promise<void>;
|
|
16
|
-
|
|
1
|
+
import {StorageObject} from "./StorageObject";
|
|
2
|
+
|
|
3
|
+
export interface IStorageManager<T extends StorageObject> {
|
|
4
|
+
|
|
5
|
+
data: {
|
|
6
|
+
[key: string]: T
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
init(): Promise<void>;
|
|
10
|
+
saveData(hash: string, object: T): Promise<void>;
|
|
11
|
+
removeData(hash: string): Promise<void>;
|
|
12
|
+
loadData(type: new(data: any) => T): Promise<T[]>;
|
|
13
|
+
|
|
14
|
+
removeDataArr?(keys: string[]): Promise<void>;
|
|
15
|
+
saveDataArr?(values: {id: string, object: T}[]): Promise<void>;
|
|
16
|
+
|
|
17
17
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export interface StorageObject {
|
|
4
|
-
|
|
5
|
-
serialize(): any;
|
|
6
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export interface StorageObject {
|
|
4
|
+
|
|
5
|
+
serialize(): any;
|
|
6
|
+
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export enum ChainSwapType {
|
|
2
|
-
HTLC = 0,
|
|
3
|
-
CHAIN = 1,
|
|
4
|
-
CHAIN_NONCED = 2,
|
|
5
|
-
CHAIN_TXID = 3
|
|
6
|
-
}
|
|
1
|
+
export enum ChainSwapType {
|
|
2
|
+
HTLC = 0,
|
|
3
|
+
CHAIN = 1,
|
|
4
|
+
CHAIN_NONCED = 2,
|
|
5
|
+
CHAIN_TXID = 3
|
|
6
|
+
}
|