@atomiqlabs/chain-starknet 4.0.0-dev.20 → 4.0.0-dev.22
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/dist/starknet/StarknetInitializer.d.ts +2 -1
- package/dist/starknet/StarknetInitializer.js +1 -1
- package/dist/starknet/chain/StarknetChainInterface.d.ts +8 -1
- package/dist/starknet/chain/StarknetChainInterface.js +8 -2
- package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +3 -3
- package/dist/starknet/contract/modules/StarknetContractEvents.js +1 -1
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +28 -0
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +127 -32
- package/dist/starknet/swaps/StarknetSwapContract.d.ts +6 -0
- package/dist/starknet/swaps/StarknetSwapContract.js +16 -0
- package/package.json +2 -2
- package/src/starknet/StarknetInitializer.ts +5 -3
- package/src/starknet/chain/StarknetChainInterface.ts +18 -2
- package/src/starknet/contract/modules/StarknetContractEvents.ts +5 -5
- package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +141 -33
- package/src/starknet/swaps/StarknetSwapContract.ts +21 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { constants, Provider } from "starknet";
|
|
2
2
|
import { StarknetFees } from "./chain/modules/StarknetFees";
|
|
3
|
-
import { StarknetRetryPolicy } from "./chain/StarknetChainInterface";
|
|
3
|
+
import { StarknetConfig, StarknetRetryPolicy } from "./chain/StarknetChainInterface";
|
|
4
4
|
import { BaseTokenType, BitcoinNetwork, BitcoinRpc, ChainData, ChainInitializer, ChainSwapType } from "@atomiqlabs/base";
|
|
5
5
|
import { StarknetChainType } from "./StarknetChainType";
|
|
6
6
|
export type StarknetAssetsType = BaseTokenType<"ETH" | "STRK" | "WBTC">;
|
|
@@ -21,6 +21,7 @@ export type StarknetOptions = {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
fees?: StarknetFees;
|
|
24
|
+
starknetConfig?: StarknetConfig;
|
|
24
25
|
};
|
|
25
26
|
export declare function initializeStarknet(options: StarknetOptions, bitcoinRpc: BitcoinRpc<any>, network: BitcoinNetwork): ChainData<StarknetChainType>;
|
|
26
27
|
export type StarknetInitializerType = ChainInitializer<StarknetOptions, StarknetChainType, StarknetAssetsType>;
|
|
@@ -41,7 +41,7 @@ function initializeStarknet(options, bitcoinRpc, network) {
|
|
|
41
41
|
const Fees = options.fees ?? new StarknetFees_1.StarknetFees(provider);
|
|
42
42
|
const chainId = options.chainId ??
|
|
43
43
|
(network === base_1.BitcoinNetwork.MAINNET ? starknet_1.constants.StarknetChainId.SN_MAIN : starknet_1.constants.StarknetChainId.SN_SEPOLIA);
|
|
44
|
-
const chainInterface = new StarknetChainInterface_1.StarknetChainInterface(chainId, provider, options.retryPolicy, Fees);
|
|
44
|
+
const chainInterface = new StarknetChainInterface_1.StarknetChainInterface(chainId, provider, options.retryPolicy, Fees, options.starknetConfig);
|
|
45
45
|
const btcRelay = new StarknetBtcRelay_1.StarknetBtcRelay(chainInterface, bitcoinRpc, network, options.btcRelayContract);
|
|
46
46
|
const swapContract = new StarknetSwapContract_1.StarknetSwapContract(chainInterface, btcRelay, options.swapContract, options.handlerContracts);
|
|
47
47
|
const spvVaultContract = new StarknetSpvVaultContract_1.StarknetSpvVaultContract(chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract);
|
|
@@ -13,6 +13,12 @@ export type StarknetRetryPolicy = {
|
|
|
13
13
|
delay?: number;
|
|
14
14
|
exponential?: boolean;
|
|
15
15
|
};
|
|
16
|
+
export type StarknetConfig = {
|
|
17
|
+
getLogChunkSize?: number;
|
|
18
|
+
getLogForwardBlockRange?: number;
|
|
19
|
+
maxGetLogKeys?: number;
|
|
20
|
+
maxParallelCalls?: number;
|
|
21
|
+
};
|
|
16
22
|
export declare class StarknetChainInterface implements ChainInterface {
|
|
17
23
|
readonly chainId = "STARKNET";
|
|
18
24
|
readonly provider: Provider;
|
|
@@ -31,7 +37,8 @@ export declare class StarknetChainInterface implements ChainInterface {
|
|
|
31
37
|
warn: (msg: any, ...args: any[]) => void;
|
|
32
38
|
error: (msg: any, ...args: any[]) => void;
|
|
33
39
|
};
|
|
34
|
-
|
|
40
|
+
readonly config: StarknetConfig;
|
|
41
|
+
constructor(chainId: constants.StarknetChainId, provider: Provider, retryPolicy?: StarknetRetryPolicy, feeEstimator?: StarknetFees, options?: StarknetConfig);
|
|
35
42
|
getBalance(signer: string, tokenAddress: string): Promise<bigint>;
|
|
36
43
|
getNativeCurrencyAddress(): string;
|
|
37
44
|
isValidToken(tokenIdentifier: string): boolean;
|
|
@@ -15,13 +15,19 @@ const StarknetSigner_1 = require("../wallet/StarknetSigner");
|
|
|
15
15
|
const buffer_1 = require("buffer");
|
|
16
16
|
const StarknetKeypairWallet_1 = require("../wallet/StarknetKeypairWallet");
|
|
17
17
|
class StarknetChainInterface {
|
|
18
|
-
constructor(chainId, provider, retryPolicy,
|
|
18
|
+
constructor(chainId, provider, retryPolicy, feeEstimator = new StarknetFees_1.StarknetFees(provider), options) {
|
|
19
|
+
var _a, _b, _c, _d;
|
|
19
20
|
this.chainId = "STARKNET";
|
|
20
21
|
this.logger = (0, Utils_1.getLogger)("StarknetChainInterface: ");
|
|
21
22
|
this.starknetChainId = chainId;
|
|
22
23
|
this.provider = provider;
|
|
23
24
|
this.retryPolicy = retryPolicy;
|
|
24
|
-
this.
|
|
25
|
+
this.config = options ?? {};
|
|
26
|
+
(_a = this.config).getLogForwardBlockRange ?? (_a.getLogForwardBlockRange = 2000);
|
|
27
|
+
(_b = this.config).getLogChunkSize ?? (_b.getLogChunkSize = 100);
|
|
28
|
+
(_c = this.config).maxGetLogKeys ?? (_c.maxGetLogKeys = 64);
|
|
29
|
+
(_d = this.config).maxParallelCalls ?? (_d.maxParallelCalls = 10);
|
|
30
|
+
this.Fees = feeEstimator;
|
|
25
31
|
this.Tokens = new StarknetTokens_1.StarknetTokens(this);
|
|
26
32
|
this.Transactions = new StarknetTransactions_1.StarknetTransactions(this);
|
|
27
33
|
this.Signatures = new StarknetSignatures_1.StarknetSignatures(this);
|
|
@@ -27,7 +27,7 @@ export declare class StarknetContractEvents<TAbi extends Abi> extends StarknetEv
|
|
|
27
27
|
* @param startBlockHeight
|
|
28
28
|
* @param endBlockHeight
|
|
29
29
|
*/
|
|
30
|
-
getContractBlockEvents<T extends ExtractAbiEventNames<TAbi>>(events: T[], keys: string[], startBlockHeight?: number, endBlockHeight?: number): Promise<StarknetAbiEvent<TAbi, T>[]>;
|
|
30
|
+
getContractBlockEvents<T extends ExtractAbiEventNames<TAbi>>(events: T[], keys: (string | string[])[], startBlockHeight?: number, endBlockHeight?: number): Promise<StarknetAbiEvent<TAbi, T>[]>;
|
|
31
31
|
/**
|
|
32
32
|
* Runs a search backwards in time, processing the events for a specific topic public key
|
|
33
33
|
*
|
|
@@ -37,7 +37,7 @@ export declare class StarknetContractEvents<TAbi extends Abi> extends StarknetEv
|
|
|
37
37
|
* if the search should continue
|
|
38
38
|
* @param abortSignal
|
|
39
39
|
*/
|
|
40
|
-
findInContractEvents<T, TEvent extends ExtractAbiEventNames<TAbi>>(events: TEvent[], keys: string[], processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>, abortSignal?: AbortSignal): Promise<T>;
|
|
40
|
+
findInContractEvents<T, TEvent extends ExtractAbiEventNames<TAbi>>(events: TEvent[], keys: (string | string[])[], processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>, abortSignal?: AbortSignal): Promise<T>;
|
|
41
41
|
/**
|
|
42
42
|
* Runs a search forwards in time, processing the events for a specific topic public key
|
|
43
43
|
*
|
|
@@ -47,5 +47,5 @@ export declare class StarknetContractEvents<TAbi extends Abi> extends StarknetEv
|
|
|
47
47
|
* if the search should continue
|
|
48
48
|
* @param abortSignal
|
|
49
49
|
*/
|
|
50
|
-
findInContractEventsForward<T, TEvent extends ExtractAbiEventNames<TAbi>>(events: TEvent[], keys: string[], processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>, abortSignal?: AbortSignal): Promise<T>;
|
|
50
|
+
findInContractEventsForward<T, TEvent extends ExtractAbiEventNames<TAbi>>(events: TEvent[], keys: (string | string[])[], processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>, abortSignal?: AbortSignal): Promise<T>;
|
|
51
51
|
}
|
|
@@ -39,7 +39,7 @@ class StarknetContractEvents extends StarknetEvents_1.StarknetEvents {
|
|
|
39
39
|
return (0, Utils_1.toHex)(starknet_1.hash.starknetKeccak(eventName));
|
|
40
40
|
}));
|
|
41
41
|
if (keys != null)
|
|
42
|
-
keys.forEach(key => filterArray.push(key == null ? [] : [key]));
|
|
42
|
+
keys.forEach(key => filterArray.push(key == null ? [] : Array.isArray(key) ? key : [key]));
|
|
43
43
|
return filterArray;
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
@@ -31,8 +31,36 @@ export declare class StarknetSpvVaultContract extends StarknetContractBase<typeo
|
|
|
31
31
|
checkWithdrawalTx(tx: SpvWithdrawalTransactionData): Promise<void>;
|
|
32
32
|
createVaultData(owner: string, vaultId: bigint, utxo: string, confirmations: number, tokenData: SpvVaultTokenData[]): Promise<StarknetSpvVaultData>;
|
|
33
33
|
getVaultData(owner: string, vaultId: bigint): Promise<StarknetSpvVaultData>;
|
|
34
|
+
getMultipleVaultData(vaults: {
|
|
35
|
+
owner: string;
|
|
36
|
+
vaultId: bigint;
|
|
37
|
+
}[]): Promise<{
|
|
38
|
+
[owner: string]: {
|
|
39
|
+
[vaultId: string]: StarknetSpvVaultData;
|
|
40
|
+
};
|
|
41
|
+
}>;
|
|
42
|
+
getVaultLatestUtxo(owner: string, vaultId: bigint): Promise<string | null>;
|
|
43
|
+
getVaultLatestUtxos(vaults: {
|
|
44
|
+
owner: string;
|
|
45
|
+
vaultId: bigint;
|
|
46
|
+
}[]): Promise<{
|
|
47
|
+
[owner: string]: {
|
|
48
|
+
[vaultId: string]: string | null;
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
34
51
|
getAllVaults(owner?: string): Promise<StarknetSpvVaultData[]>;
|
|
35
52
|
getFronterAddress(owner: string, vaultId: bigint, withdrawal: StarknetSpvWithdrawalData): Promise<string | null>;
|
|
53
|
+
getFronterAddresses(withdrawals: {
|
|
54
|
+
owner: string;
|
|
55
|
+
vaultId: bigint;
|
|
56
|
+
withdrawal: StarknetSpvWithdrawalData;
|
|
57
|
+
}[]): Promise<{
|
|
58
|
+
[btcTxId: string]: string | null;
|
|
59
|
+
}>;
|
|
60
|
+
private parseWithdrawalEvent;
|
|
61
|
+
getWithdrawalStates(btcTxIds: string[]): Promise<{
|
|
62
|
+
[btcTxId: string]: SpvWithdrawalState;
|
|
63
|
+
}>;
|
|
36
64
|
getWithdrawalState(btcTxId: string): Promise<SpvWithdrawalState>;
|
|
37
65
|
getWithdrawalData(btcTx: BtcTx): Promise<StarknetSpvWithdrawalData>;
|
|
38
66
|
fromOpReturnData(data: Buffer): {
|
|
@@ -97,6 +97,48 @@ class StarknetSpvVaultContract extends StarknetContractBase_1.StarknetContractBa
|
|
|
97
97
|
return null;
|
|
98
98
|
return new StarknetSpvVaultData_1.StarknetSpvVaultData(owner, vaultId, struct);
|
|
99
99
|
}
|
|
100
|
+
async getMultipleVaultData(vaults) {
|
|
101
|
+
const result = {};
|
|
102
|
+
let promises = [];
|
|
103
|
+
//TODO: We can upgrade this to use multicall
|
|
104
|
+
for (let { owner, vaultId } of vaults) {
|
|
105
|
+
promises.push(this.getVaultData(owner, vaultId).then(val => {
|
|
106
|
+
result[owner] ?? (result[owner] = {});
|
|
107
|
+
result[owner][vaultId.toString(10)] = val;
|
|
108
|
+
}));
|
|
109
|
+
if (promises.length >= this.Chain.config.maxParallelCalls) {
|
|
110
|
+
await Promise.all(promises);
|
|
111
|
+
promises = [];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
await Promise.all(promises);
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
async getVaultLatestUtxo(owner, vaultId) {
|
|
118
|
+
const vault = await this.getVaultData(owner, vaultId);
|
|
119
|
+
if (vault == null)
|
|
120
|
+
return null;
|
|
121
|
+
if (!vault.isOpened())
|
|
122
|
+
return null;
|
|
123
|
+
return vault.getUtxo();
|
|
124
|
+
}
|
|
125
|
+
async getVaultLatestUtxos(vaults) {
|
|
126
|
+
const result = {};
|
|
127
|
+
let promises = [];
|
|
128
|
+
//TODO: We can upgrade this to use multicall
|
|
129
|
+
for (let { owner, vaultId } of vaults) {
|
|
130
|
+
promises.push(this.getVaultLatestUtxo(owner, vaultId).then(val => {
|
|
131
|
+
result[owner] ?? (result[owner] = {});
|
|
132
|
+
result[owner][vaultId.toString(10)] = val;
|
|
133
|
+
}));
|
|
134
|
+
if (promises.length >= this.Chain.config.maxParallelCalls) {
|
|
135
|
+
await Promise.all(promises);
|
|
136
|
+
promises = [];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
await Promise.all(promises);
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
100
142
|
async getAllVaults(owner) {
|
|
101
143
|
const openedVaults = new Set();
|
|
102
144
|
await this.Events.findInContractEventsForward(["spv_swap_vault::events::Opened", "spv_swap_vault::events::Closed"], owner == null ? null : [null, owner], (event) => {
|
|
@@ -126,6 +168,88 @@ class StarknetSpvVaultContract extends StarknetContractBase_1.StarknetContractBa
|
|
|
126
168
|
return null;
|
|
127
169
|
return fronterAddress;
|
|
128
170
|
}
|
|
171
|
+
async getFronterAddresses(withdrawals) {
|
|
172
|
+
const result = {};
|
|
173
|
+
let promises = [];
|
|
174
|
+
//TODO: We can upgrade this to use multicall
|
|
175
|
+
for (let { owner, vaultId, withdrawal } of withdrawals) {
|
|
176
|
+
promises.push(this.getFronterAddress(owner, vaultId, withdrawal).then(val => {
|
|
177
|
+
result[withdrawal.getTxId()] = val;
|
|
178
|
+
}));
|
|
179
|
+
if (promises.length >= this.Chain.config.maxParallelCalls) {
|
|
180
|
+
await Promise.all(promises);
|
|
181
|
+
promises = [];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
await Promise.all(promises);
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
parseWithdrawalEvent(event) {
|
|
188
|
+
switch (event.name) {
|
|
189
|
+
case "spv_swap_vault::events::Fronted":
|
|
190
|
+
return {
|
|
191
|
+
type: base_1.SpvWithdrawalStateType.FRONTED,
|
|
192
|
+
txId: event.txHash,
|
|
193
|
+
owner: (0, Utils_1.toHex)(event.params.owner),
|
|
194
|
+
vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
|
|
195
|
+
recipient: (0, Utils_1.toHex)(event.params.recipient),
|
|
196
|
+
fronter: (0, Utils_1.toHex)(event.params.fronting_address)
|
|
197
|
+
};
|
|
198
|
+
case "spv_swap_vault::events::Claimed":
|
|
199
|
+
return {
|
|
200
|
+
type: base_1.SpvWithdrawalStateType.CLAIMED,
|
|
201
|
+
txId: event.txHash,
|
|
202
|
+
owner: (0, Utils_1.toHex)(event.params.owner),
|
|
203
|
+
vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
|
|
204
|
+
recipient: (0, Utils_1.toHex)(event.params.recipient),
|
|
205
|
+
claimer: (0, Utils_1.toHex)(event.params.caller),
|
|
206
|
+
fronter: (0, Utils_1.toHex)(event.params.fronting_address)
|
|
207
|
+
};
|
|
208
|
+
case "spv_swap_vault::events::Closed":
|
|
209
|
+
return {
|
|
210
|
+
type: base_1.SpvWithdrawalStateType.CLOSED,
|
|
211
|
+
txId: event.txHash,
|
|
212
|
+
owner: (0, Utils_1.toHex)(event.params.owner),
|
|
213
|
+
vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
|
|
214
|
+
error: (0, Utils_1.bigNumberishToBuffer)(event.params.error).toString()
|
|
215
|
+
};
|
|
216
|
+
default:
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async getWithdrawalStates(btcTxIds) {
|
|
221
|
+
const result = {};
|
|
222
|
+
btcTxIds.forEach(txId => {
|
|
223
|
+
result[txId] = {
|
|
224
|
+
type: base_1.SpvWithdrawalStateType.NOT_FOUND
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
for (let i = 0; i < btcTxIds.length; i += this.Chain.config.maxGetLogKeys) {
|
|
228
|
+
const checkBtcTxIds = btcTxIds.slice(i, i + this.Chain.config.maxGetLogKeys);
|
|
229
|
+
const lows = [];
|
|
230
|
+
const highs = [];
|
|
231
|
+
checkBtcTxIds.forEach(btcTxId => {
|
|
232
|
+
const txHash = buffer_1.Buffer.from(btcTxId, "hex").reverse();
|
|
233
|
+
const txHashU256 = starknet_1.cairo.uint256("0x" + txHash.toString("hex"));
|
|
234
|
+
lows.push((0, Utils_1.toHex)(txHashU256.low));
|
|
235
|
+
highs.push((0, Utils_1.toHex)(txHashU256.high));
|
|
236
|
+
});
|
|
237
|
+
await this.Events.findInContractEventsForward(["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"], [
|
|
238
|
+
lows,
|
|
239
|
+
highs
|
|
240
|
+
], async (event) => {
|
|
241
|
+
const txId = (0, Utils_1.bigNumberishToBuffer)(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
242
|
+
if (result[txId] == null) {
|
|
243
|
+
this.logger.warn(`getWithdrawalStates(): findInContractEvents-callback: loaded event for ${txId}, but transaction not found in input params!`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const eventResult = this.parseWithdrawalEvent(event);
|
|
247
|
+
if (eventResult != null)
|
|
248
|
+
result[txId] = eventResult;
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
129
253
|
async getWithdrawalState(btcTxId) {
|
|
130
254
|
const txHash = buffer_1.Buffer.from(btcTxId, "hex").reverse();
|
|
131
255
|
const txHashU256 = starknet_1.cairo.uint256("0x" + txHash.toString("hex"));
|
|
@@ -136,38 +260,9 @@ class StarknetSpvVaultContract extends StarknetContractBase_1.StarknetContractBa
|
|
|
136
260
|
(0, Utils_1.toHex)(txHashU256.low),
|
|
137
261
|
(0, Utils_1.toHex)(txHashU256.high)
|
|
138
262
|
], async (event) => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
type: base_1.SpvWithdrawalStateType.FRONTED,
|
|
143
|
-
txId: event.txHash,
|
|
144
|
-
owner: (0, Utils_1.toHex)(event.params.owner),
|
|
145
|
-
vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
|
|
146
|
-
recipient: (0, Utils_1.toHex)(event.params.recipient),
|
|
147
|
-
fronter: (0, Utils_1.toHex)(event.params.fronting_address)
|
|
148
|
-
};
|
|
149
|
-
break;
|
|
150
|
-
case "spv_swap_vault::events::Claimed":
|
|
151
|
-
result = {
|
|
152
|
-
type: base_1.SpvWithdrawalStateType.CLAIMED,
|
|
153
|
-
txId: event.txHash,
|
|
154
|
-
owner: (0, Utils_1.toHex)(event.params.owner),
|
|
155
|
-
vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
|
|
156
|
-
recipient: (0, Utils_1.toHex)(event.params.recipient),
|
|
157
|
-
claimer: (0, Utils_1.toHex)(event.params.caller),
|
|
158
|
-
fronter: (0, Utils_1.toHex)(event.params.fronting_address)
|
|
159
|
-
};
|
|
160
|
-
break;
|
|
161
|
-
case "spv_swap_vault::events::Closed":
|
|
162
|
-
result = {
|
|
163
|
-
type: base_1.SpvWithdrawalStateType.CLOSED,
|
|
164
|
-
txId: event.txHash,
|
|
165
|
-
owner: (0, Utils_1.toHex)(event.params.owner),
|
|
166
|
-
vaultId: (0, Utils_1.toBigInt)(event.params.vault_id),
|
|
167
|
-
error: (0, Utils_1.bigNumberishToBuffer)(event.params.error).toString()
|
|
168
|
-
};
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
263
|
+
const eventResult = this.parseWithdrawalEvent(event);
|
|
264
|
+
if (eventResult != null)
|
|
265
|
+
result = eventResult;
|
|
171
266
|
});
|
|
172
267
|
return result;
|
|
173
268
|
}
|
|
@@ -126,6 +126,12 @@ export declare class StarknetSwapContract extends StarknetContractBase<typeof Es
|
|
|
126
126
|
* @param data
|
|
127
127
|
*/
|
|
128
128
|
getCommitStatus(signer: string, data: StarknetSwapData): Promise<SwapCommitState>;
|
|
129
|
+
getCommitStatuses(request: {
|
|
130
|
+
signer: string;
|
|
131
|
+
swapData: StarknetSwapData;
|
|
132
|
+
}[]): Promise<{
|
|
133
|
+
[p: string]: SwapCommitState;
|
|
134
|
+
}>;
|
|
129
135
|
/**
|
|
130
136
|
* Returns the data committed for a specific payment hash, or null if no data is currently commited for
|
|
131
137
|
* the specific swap
|
|
@@ -287,6 +287,22 @@ class StarknetSwapContract extends StarknetContractBase_1.StarknetContractBase {
|
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
|
+
async getCommitStatuses(request) {
|
|
291
|
+
const result = {};
|
|
292
|
+
let promises = [];
|
|
293
|
+
//TODO: We can upgrade this to use multicall
|
|
294
|
+
for (let { signer, swapData } of request) {
|
|
295
|
+
promises.push(this.getCommitStatus(signer, swapData).then(val => {
|
|
296
|
+
result[swapData.getEscrowHash()] = val;
|
|
297
|
+
}));
|
|
298
|
+
if (promises.length >= this.Chain.config.maxParallelCalls) {
|
|
299
|
+
await Promise.all(promises);
|
|
300
|
+
promises = [];
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
await Promise.all(promises);
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
290
306
|
/**
|
|
291
307
|
* Returns the data committed for a specific payment hash, or null if no data is currently commited for
|
|
292
308
|
* the specific swap
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomiqlabs/chain-starknet",
|
|
3
|
-
"version": "4.0.0-dev.
|
|
3
|
+
"version": "4.0.0-dev.22",
|
|
4
4
|
"description": "Starknet specific base implementation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"url": "git+https://github.com/atomiqlabs/atomiq-chain-starknet.git"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@atomiqlabs/base": "^10.0.0-dev.
|
|
31
|
+
"@atomiqlabs/base": "^10.0.0-dev.13",
|
|
32
32
|
"@noble/hashes": "^1.7.1",
|
|
33
33
|
"@scure/btc-signer": "^1.6.0",
|
|
34
34
|
"abi-wan-kanabi": "2.2.4",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {constants, Provider} from "starknet";
|
|
2
2
|
import {StarknetFees} from "./chain/modules/StarknetFees";
|
|
3
|
-
import {StarknetChainInterface, StarknetRetryPolicy} from "./chain/StarknetChainInterface";
|
|
3
|
+
import {StarknetChainInterface, StarknetConfig, StarknetRetryPolicy} from "./chain/StarknetChainInterface";
|
|
4
4
|
import {StarknetBtcRelay} from "./btcrelay/StarknetBtcRelay";
|
|
5
5
|
import {StarknetSwapContract} from "./swaps/StarknetSwapContract";
|
|
6
6
|
import {StarknetChainEventsBrowser} from "./events/StarknetChainEventsBrowser";
|
|
@@ -52,7 +52,9 @@ export type StarknetOptions = {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
fees?: StarknetFees
|
|
55
|
+
fees?: StarknetFees,
|
|
56
|
+
|
|
57
|
+
starknetConfig?: StarknetConfig
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
export function initializeStarknet(
|
|
@@ -69,7 +71,7 @@ export function initializeStarknet(
|
|
|
69
71
|
const chainId = options.chainId ??
|
|
70
72
|
(network===BitcoinNetwork.MAINNET ? constants.StarknetChainId.SN_MAIN : constants.StarknetChainId.SN_SEPOLIA);
|
|
71
73
|
|
|
72
|
-
const chainInterface = new StarknetChainInterface(chainId, provider, options.retryPolicy, Fees);
|
|
74
|
+
const chainInterface = new StarknetChainInterface(chainId, provider, options.retryPolicy, Fees, options.starknetConfig);
|
|
73
75
|
|
|
74
76
|
const btcRelay = new StarknetBtcRelay(
|
|
75
77
|
chainInterface, bitcoinRpc, network, options.btcRelayContract
|
|
@@ -19,6 +19,14 @@ export type StarknetRetryPolicy = {
|
|
|
19
19
|
exponential?: boolean
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
export type StarknetConfig = {
|
|
23
|
+
getLogChunkSize?: number, //100
|
|
24
|
+
getLogForwardBlockRange?: number, //2000
|
|
25
|
+
maxGetLogKeys?: number, //64
|
|
26
|
+
|
|
27
|
+
maxParallelCalls?: number, //10
|
|
28
|
+
};
|
|
29
|
+
|
|
22
30
|
export class StarknetChainInterface implements ChainInterface {
|
|
23
31
|
|
|
24
32
|
readonly chainId = "STARKNET";
|
|
@@ -38,17 +46,25 @@ export class StarknetChainInterface implements ChainInterface {
|
|
|
38
46
|
|
|
39
47
|
protected readonly logger = getLogger("StarknetChainInterface: ");
|
|
40
48
|
|
|
49
|
+
public readonly config: StarknetConfig;
|
|
50
|
+
|
|
41
51
|
constructor(
|
|
42
52
|
chainId: constants.StarknetChainId,
|
|
43
53
|
provider: Provider,
|
|
44
54
|
retryPolicy?: StarknetRetryPolicy,
|
|
45
|
-
|
|
55
|
+
feeEstimator: StarknetFees = new StarknetFees(provider),
|
|
56
|
+
options?: StarknetConfig
|
|
46
57
|
) {
|
|
47
58
|
this.starknetChainId = chainId;
|
|
48
59
|
this.provider = provider;
|
|
49
60
|
this.retryPolicy = retryPolicy;
|
|
61
|
+
this.config = options ?? {};
|
|
62
|
+
this.config.getLogForwardBlockRange ??= 2000;
|
|
63
|
+
this.config.getLogChunkSize ??= 100;
|
|
64
|
+
this.config.maxGetLogKeys ??= 64;
|
|
65
|
+
this.config.maxParallelCalls ??= 10;
|
|
50
66
|
|
|
51
|
-
this.Fees =
|
|
67
|
+
this.Fees = feeEstimator;
|
|
52
68
|
this.Tokens = new StarknetTokens(this);
|
|
53
69
|
this.Transactions = new StarknetTransactions(this);
|
|
54
70
|
|
|
@@ -51,7 +51,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
51
51
|
|
|
52
52
|
private toFilter<T extends ExtractAbiEventNames<TAbi>>(
|
|
53
53
|
events: T[],
|
|
54
|
-
keys: string[],
|
|
54
|
+
keys: (string | string[])[],
|
|
55
55
|
): string[][] {
|
|
56
56
|
const filterArray: string[][] = [];
|
|
57
57
|
filterArray.push(events.map(name => {
|
|
@@ -59,7 +59,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
59
59
|
const eventName = arr[arr.length-1];
|
|
60
60
|
return toHex(hash.starknetKeccak(eventName))
|
|
61
61
|
}));
|
|
62
|
-
if(keys!=null) keys.forEach(key => filterArray.push(key==null ? [] : [key]));
|
|
62
|
+
if(keys!=null) keys.forEach(key => filterArray.push(key==null ? [] : Array.isArray(key) ? key : [key]));
|
|
63
63
|
return filterArray;
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -74,7 +74,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
74
74
|
*/
|
|
75
75
|
public async getContractBlockEvents<T extends ExtractAbiEventNames<TAbi>>(
|
|
76
76
|
events: T[],
|
|
77
|
-
keys: string[],
|
|
77
|
+
keys: (string | string[])[],
|
|
78
78
|
startBlockHeight?: number,
|
|
79
79
|
endBlockHeight: number = startBlockHeight
|
|
80
80
|
): Promise<StarknetAbiEvent<TAbi, T>[]> {
|
|
@@ -93,7 +93,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
93
93
|
*/
|
|
94
94
|
public async findInContractEvents<T, TEvent extends ExtractAbiEventNames<TAbi>>(
|
|
95
95
|
events: TEvent[],
|
|
96
|
-
keys: string[],
|
|
96
|
+
keys: (string | string[])[],
|
|
97
97
|
processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>,
|
|
98
98
|
abortSignal?: AbortSignal
|
|
99
99
|
) {
|
|
@@ -117,7 +117,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
117
117
|
*/
|
|
118
118
|
public async findInContractEventsForward<T, TEvent extends ExtractAbiEventNames<TAbi>>(
|
|
119
119
|
events: TEvent[],
|
|
120
|
-
keys: string[],
|
|
120
|
+
keys: (string | string[])[],
|
|
121
121
|
processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>,
|
|
122
122
|
abortSignal?: AbortSignal
|
|
123
123
|
) {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
SpvVaultTokenData,
|
|
7
7
|
SpvWithdrawalState,
|
|
8
8
|
SpvWithdrawalStateType,
|
|
9
|
-
SpvWithdrawalTransactionData,
|
|
9
|
+
SpvWithdrawalTransactionData, SwapCommitState,
|
|
10
10
|
TransactionConfirmationOptions
|
|
11
11
|
} from "@atomiqlabs/base";
|
|
12
12
|
import {Buffer} from "buffer";
|
|
@@ -24,6 +24,9 @@ import {bigNumberishToBuffer, bufferToByteArray, bufferToU32Array, getLogger, to
|
|
|
24
24
|
import {StarknetBtcStoredHeader} from "../btcrelay/headers/StarknetBtcStoredHeader";
|
|
25
25
|
import {StarknetAddresses} from "../chain/modules/StarknetAddresses";
|
|
26
26
|
import {StarknetFees} from "../chain/modules/StarknetFees";
|
|
27
|
+
import {toBig} from "@noble/hashes/_u64";
|
|
28
|
+
import {StarknetAbiEvent} from "../contract/modules/StarknetContractEvents";
|
|
29
|
+
import {ExtractAbiEventNames} from "abi-wan-kanabi/dist/kanabi";
|
|
27
30
|
|
|
28
31
|
const spvVaultContractAddreses = {
|
|
29
32
|
[constants.StarknetChainId.SN_SEPOLIA]: "0x02d581ea838cd5ca46ba08660eddd064d50a0392f618e95310432147928d572e",
|
|
@@ -166,6 +169,49 @@ export class StarknetSpvVaultContract
|
|
|
166
169
|
return new StarknetSpvVaultData(owner, vaultId, struct);
|
|
167
170
|
}
|
|
168
171
|
|
|
172
|
+
async getMultipleVaultData(vaults: {owner: string, vaultId: bigint}[]): Promise<{[owner: string]: {[vaultId: string]: StarknetSpvVaultData}}> {
|
|
173
|
+
const result: {[owner: string]: {[vaultId: string]: StarknetSpvVaultData}} = {};
|
|
174
|
+
let promises: Promise<void>[] = [];
|
|
175
|
+
//TODO: We can upgrade this to use multicall
|
|
176
|
+
for(let {owner, vaultId} of vaults) {
|
|
177
|
+
promises.push(this.getVaultData(owner, vaultId).then(val => {
|
|
178
|
+
result[owner] ??= {};
|
|
179
|
+
result[owner][vaultId.toString(10)] = val;
|
|
180
|
+
}));
|
|
181
|
+
if(promises.length>=this.Chain.config.maxParallelCalls) {
|
|
182
|
+
await Promise.all(promises);
|
|
183
|
+
promises = [];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
await Promise.all(promises);
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async getVaultLatestUtxo(owner: string, vaultId: bigint): Promise<string | null> {
|
|
191
|
+
const vault = await this.getVaultData(owner, vaultId);
|
|
192
|
+
if(vault==null) return null;
|
|
193
|
+
if(!vault.isOpened()) return null;
|
|
194
|
+
return vault.getUtxo();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async getVaultLatestUtxos(vaults: {owner: string, vaultId: bigint}[]): Promise<{[owner: string]: {[vaultId: string]: string | null}}> {
|
|
198
|
+
const result: {[owner: string]: {[vaultId: string]: string | null}} = {};
|
|
199
|
+
let promises: Promise<void>[] = [];
|
|
200
|
+
//TODO: We can upgrade this to use multicall
|
|
201
|
+
for(let {owner, vaultId} of vaults) {
|
|
202
|
+
promises.push(this.getVaultLatestUtxo(owner, vaultId).then(val => {
|
|
203
|
+
result[owner] ??= {};
|
|
204
|
+
result[owner][vaultId.toString(10)] = val;
|
|
205
|
+
}));
|
|
206
|
+
if(promises.length>=this.Chain.config.maxParallelCalls) {
|
|
207
|
+
await Promise.all(promises);
|
|
208
|
+
promises = [];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
await Promise.all(promises);
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
|
|
169
215
|
async getAllVaults(owner?: string): Promise<StarknetSpvVaultData[]> {
|
|
170
216
|
const openedVaults = new Set<string>();
|
|
171
217
|
await this.Events.findInContractEventsForward(
|
|
@@ -198,6 +244,98 @@ export class StarknetSpvVaultContract
|
|
|
198
244
|
return fronterAddress;
|
|
199
245
|
}
|
|
200
246
|
|
|
247
|
+
async getFronterAddresses(withdrawals: {owner: string, vaultId: bigint, withdrawal: StarknetSpvWithdrawalData}[]): Promise<{[btcTxId: string]: string | null}> {
|
|
248
|
+
const result: {
|
|
249
|
+
[btcTxId: string]: string | null
|
|
250
|
+
} = {};
|
|
251
|
+
let promises: Promise<void>[] = [];
|
|
252
|
+
//TODO: We can upgrade this to use multicall
|
|
253
|
+
for(let {owner, vaultId, withdrawal} of withdrawals) {
|
|
254
|
+
promises.push(this.getFronterAddress(owner, vaultId, withdrawal).then(val => {
|
|
255
|
+
result[withdrawal.getTxId()] = val;
|
|
256
|
+
}));
|
|
257
|
+
if(promises.length>=this.Chain.config.maxParallelCalls) {
|
|
258
|
+
await Promise.all(promises);
|
|
259
|
+
promises = [];
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
await Promise.all(promises);
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private parseWithdrawalEvent(event: StarknetAbiEvent<typeof SpvVaultContractAbi, "spv_swap_vault::events::Claimed" | "spv_swap_vault::events::Fronted" | "spv_swap_vault::events::Closed">): SpvWithdrawalState | null {
|
|
267
|
+
switch(event.name) {
|
|
268
|
+
case "spv_swap_vault::events::Fronted":
|
|
269
|
+
return {
|
|
270
|
+
type: SpvWithdrawalStateType.FRONTED,
|
|
271
|
+
txId: event.txHash,
|
|
272
|
+
owner: toHex(event.params.owner),
|
|
273
|
+
vaultId: toBigInt(event.params.vault_id),
|
|
274
|
+
recipient: toHex(event.params.recipient),
|
|
275
|
+
fronter: toHex(event.params.fronting_address)
|
|
276
|
+
};
|
|
277
|
+
case "spv_swap_vault::events::Claimed":
|
|
278
|
+
return {
|
|
279
|
+
type: SpvWithdrawalStateType.CLAIMED,
|
|
280
|
+
txId: event.txHash,
|
|
281
|
+
owner: toHex(event.params.owner),
|
|
282
|
+
vaultId: toBigInt(event.params.vault_id),
|
|
283
|
+
recipient: toHex(event.params.recipient),
|
|
284
|
+
claimer: toHex(event.params.caller),
|
|
285
|
+
fronter: toHex(event.params.fronting_address)
|
|
286
|
+
};
|
|
287
|
+
case "spv_swap_vault::events::Closed":
|
|
288
|
+
return {
|
|
289
|
+
type: SpvWithdrawalStateType.CLOSED,
|
|
290
|
+
txId: event.txHash,
|
|
291
|
+
owner: toHex(event.params.owner),
|
|
292
|
+
vaultId: toBigInt(event.params.vault_id),
|
|
293
|
+
error: bigNumberishToBuffer(event.params.error).toString()
|
|
294
|
+
};
|
|
295
|
+
default:
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async getWithdrawalStates(btcTxIds: string[]): Promise<{[btcTxId: string]: SpvWithdrawalState}> {
|
|
301
|
+
const result: {[btcTxId: string]: SpvWithdrawalState} = {};
|
|
302
|
+
btcTxIds.forEach(txId => {
|
|
303
|
+
result[txId] = {
|
|
304
|
+
type: SpvWithdrawalStateType.NOT_FOUND
|
|
305
|
+
};
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
for(let i=0;i<btcTxIds.length;i+=this.Chain.config.maxGetLogKeys) {
|
|
309
|
+
const checkBtcTxIds = btcTxIds.slice(i, i+this.Chain.config.maxGetLogKeys);
|
|
310
|
+
const lows: string[] = [];
|
|
311
|
+
const highs: string[] = [];
|
|
312
|
+
checkBtcTxIds.forEach(btcTxId => {
|
|
313
|
+
const txHash = Buffer.from(btcTxId, "hex").reverse();
|
|
314
|
+
const txHashU256 = cairo.uint256("0x"+txHash.toString("hex"));
|
|
315
|
+
lows.push(toHex(txHashU256.low));
|
|
316
|
+
highs.push(toHex(txHashU256.high));
|
|
317
|
+
});
|
|
318
|
+
await this.Events.findInContractEventsForward(
|
|
319
|
+
["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"],
|
|
320
|
+
[
|
|
321
|
+
lows,
|
|
322
|
+
highs
|
|
323
|
+
],
|
|
324
|
+
async (event) => {
|
|
325
|
+
const txId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
326
|
+
if(result[txId]==null) {
|
|
327
|
+
this.logger.warn(`getWithdrawalStates(): findInContractEvents-callback: loaded event for ${txId}, but transaction not found in input params!`)
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const eventResult = this.parseWithdrawalEvent(event);
|
|
331
|
+
if(eventResult!=null) result[txId] = eventResult;
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
|
|
201
339
|
async getWithdrawalState(btcTxId: string): Promise<SpvWithdrawalState> {
|
|
202
340
|
const txHash = Buffer.from(btcTxId, "hex").reverse();
|
|
203
341
|
const txHashU256 = cairo.uint256("0x"+txHash.toString("hex"));
|
|
@@ -211,38 +349,8 @@ export class StarknetSpvVaultContract
|
|
|
211
349
|
toHex(txHashU256.high)
|
|
212
350
|
],
|
|
213
351
|
async (event) => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
result = {
|
|
217
|
-
type: SpvWithdrawalStateType.FRONTED,
|
|
218
|
-
txId: event.txHash,
|
|
219
|
-
owner: toHex(event.params.owner),
|
|
220
|
-
vaultId: toBigInt(event.params.vault_id),
|
|
221
|
-
recipient: toHex(event.params.recipient),
|
|
222
|
-
fronter: toHex(event.params.fronting_address)
|
|
223
|
-
};
|
|
224
|
-
break;
|
|
225
|
-
case "spv_swap_vault::events::Claimed":
|
|
226
|
-
result = {
|
|
227
|
-
type: SpvWithdrawalStateType.CLAIMED,
|
|
228
|
-
txId: event.txHash,
|
|
229
|
-
owner: toHex(event.params.owner),
|
|
230
|
-
vaultId: toBigInt(event.params.vault_id),
|
|
231
|
-
recipient: toHex(event.params.recipient),
|
|
232
|
-
claimer: toHex(event.params.caller),
|
|
233
|
-
fronter: toHex(event.params.fronting_address)
|
|
234
|
-
};
|
|
235
|
-
break;
|
|
236
|
-
case "spv_swap_vault::events::Closed":
|
|
237
|
-
result = {
|
|
238
|
-
type: SpvWithdrawalStateType.CLOSED,
|
|
239
|
-
txId: event.txHash,
|
|
240
|
-
owner: toHex(event.params.owner),
|
|
241
|
-
vaultId: toBigInt(event.params.vault_id),
|
|
242
|
-
error: bigNumberishToBuffer(event.params.error).toString()
|
|
243
|
-
}
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
352
|
+
const eventResult = this.parseWithdrawalEvent(event);
|
|
353
|
+
if(eventResult!=null) result = eventResult;
|
|
246
354
|
}
|
|
247
355
|
);
|
|
248
356
|
return result;
|
|
@@ -369,6 +369,27 @@ export class StarknetSwapContract
|
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
+
async getCommitStatuses(request: { signer: string; swapData: StarknetSwapData }[]): Promise<{
|
|
373
|
+
[p: string]: SwapCommitState
|
|
374
|
+
}> {
|
|
375
|
+
const result: {
|
|
376
|
+
[p: string]: SwapCommitState
|
|
377
|
+
} = {};
|
|
378
|
+
let promises: Promise<void>[] = [];
|
|
379
|
+
//TODO: We can upgrade this to use multicall
|
|
380
|
+
for(let {signer, swapData} of request) {
|
|
381
|
+
promises.push(this.getCommitStatus(signer, swapData).then(val => {
|
|
382
|
+
result[swapData.getEscrowHash()] = val;
|
|
383
|
+
}));
|
|
384
|
+
if(promises.length>=this.Chain.config.maxParallelCalls) {
|
|
385
|
+
await Promise.all(promises);
|
|
386
|
+
promises = [];
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
await Promise.all(promises);
|
|
390
|
+
return result;
|
|
391
|
+
}
|
|
392
|
+
|
|
372
393
|
/**
|
|
373
394
|
* Returns the data committed for a specific payment hash, or null if no data is currently commited for
|
|
374
395
|
* the specific swap
|