@atomiqlabs/chain-starknet 4.0.0-dev.9 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/starknet/StarknetInitializer.d.ts +1 -9
- package/dist/starknet/StarknetInitializer.js +3 -8
- package/dist/starknet/btcrelay/StarknetBtcRelay.js +5 -5
- package/dist/starknet/chain/StarknetAction.d.ts +10 -2
- package/dist/starknet/chain/StarknetAction.js +21 -21
- package/dist/starknet/chain/modules/StarknetAccounts.js +1 -1
- package/dist/starknet/chain/modules/StarknetFees.d.ts +8 -30
- package/dist/starknet/chain/modules/StarknetFees.js +26 -40
- package/dist/starknet/chain/modules/StarknetSignatures.js +1 -1
- package/dist/starknet/chain/modules/StarknetTokens.d.ts +4 -6
- package/dist/starknet/chain/modules/StarknetTokens.js +2 -2
- package/dist/starknet/chain/modules/StarknetTransactions.js +2 -2
- package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +2 -1
- package/dist/starknet/events/StarknetChainEventsBrowser.js +3 -1
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +2 -3
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +8 -14
- package/dist/starknet/spv_swap/StarknetSpvVaultData.js +0 -1
- package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +0 -1
- package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +0 -11
- package/dist/starknet/swaps/EscrowManagerAbi.d.ts +0 -26
- package/dist/starknet/swaps/EscrowManagerAbi.js +0 -36
- package/dist/starknet/swaps/StarknetSwapContract.d.ts +2 -3
- package/dist/starknet/swaps/StarknetSwapContract.js +19 -6
- package/dist/starknet/swaps/StarknetSwapData.d.ts +1 -8
- package/dist/starknet/swaps/StarknetSwapData.js +7 -51
- package/dist/starknet/swaps/handlers/IHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.js +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.js +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.js +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.js +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +1 -1
- package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +1 -1
- package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.js +1 -1
- package/dist/starknet/swaps/modules/StarknetLpVault.js +2 -2
- package/dist/starknet/swaps/modules/StarknetSwapClaim.js +8 -8
- package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +0 -2
- package/dist/starknet/swaps/modules/StarknetSwapInit.js +10 -70
- package/dist/starknet/swaps/modules/StarknetSwapRefund.js +4 -4
- package/dist/utils/Utils.js +8 -12
- package/package.json +3 -3
- package/src/starknet/StarknetInitializer.ts +4 -17
- package/src/starknet/btcrelay/StarknetBtcRelay.ts +6 -9
- package/src/starknet/chain/StarknetAction.ts +20 -15
- package/src/starknet/chain/modules/StarknetAccounts.ts +1 -1
- package/src/starknet/chain/modules/StarknetFees.ts +31 -53
- package/src/starknet/chain/modules/StarknetSignatures.ts +4 -5
- package/src/starknet/chain/modules/StarknetTokens.ts +2 -2
- package/src/starknet/chain/modules/StarknetTransactions.ts +2 -2
- package/src/starknet/events/StarknetChainEventsBrowser.ts +3 -1
- package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +8 -14
- package/src/starknet/spv_swap/StarknetSpvVaultData.ts +0 -1
- package/src/starknet/spv_swap/StarknetSpvWithdrawalData.ts +2 -13
- package/src/starknet/swaps/EscrowManagerAbi.ts +0 -36
- package/src/starknet/swaps/StarknetSwapContract.ts +23 -8
- package/src/starknet/swaps/StarknetSwapData.ts +9 -70
- package/src/starknet/swaps/handlers/IHandler.ts +1 -1
- package/src/starknet/swaps/handlers/claim/ClaimHandlers.ts +1 -1
- package/src/starknet/swaps/handlers/claim/HashlockClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/refund/TimelockRefundHandler.ts +3 -3
- package/src/starknet/swaps/modules/StarknetLpVault.ts +2 -2
- package/src/starknet/swaps/modules/StarknetSwapClaim.ts +10 -10
- package/src/starknet/swaps/modules/StarknetSwapInit.ts +12 -71
- package/src/starknet/swaps/modules/StarknetSwapRefund.ts +7 -6
- package/src/utils/Utils.ts +6 -10
|
@@ -34,7 +34,7 @@ export type StarknetTraceCall = {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Solana on-chain event handler for front-end systems without access to fs, uses pure WS to subscribe, might lose
|
|
38
38
|
* out on some events if the network is unreliable, front-end systems should take this into consideration and not
|
|
39
39
|
* rely purely on events
|
|
40
40
|
*/
|
|
@@ -44,6 +44,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
44
44
|
protected readonly provider: Provider;
|
|
45
45
|
protected readonly starknetSwapContract: StarknetSwapContract;
|
|
46
46
|
protected readonly starknetSpvVaultContract: StarknetSpvVaultContract;
|
|
47
|
+
protected eventListeners: number[] = [];
|
|
47
48
|
protected readonly logger = getLogger("StarknetChainEventsBrowser: ");
|
|
48
49
|
|
|
49
50
|
protected initFunctionName: ExtractAbiFunctionNames<EscrowManagerAbiType> = "initialize";
|
|
@@ -393,6 +394,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
393
394
|
async stop(): Promise<void> {
|
|
394
395
|
this.stopped = true;
|
|
395
396
|
if(this.timeout!=null) clearTimeout(this.timeout);
|
|
397
|
+
this.eventListeners = [];
|
|
396
398
|
}
|
|
397
399
|
|
|
398
400
|
registerListener(cbk: EventListener<StarknetSwapData>): void {
|
|
@@ -51,10 +51,10 @@ export class StarknetSpvVaultContract
|
|
|
51
51
|
>
|
|
52
52
|
{
|
|
53
53
|
private static readonly GasCosts = {
|
|
54
|
-
DEPOSIT: {
|
|
55
|
-
OPEN: {
|
|
56
|
-
FRONT: {
|
|
57
|
-
CLAIM: {
|
|
54
|
+
DEPOSIT: {l1: 750, l2: 0},
|
|
55
|
+
OPEN: {l1: 1500, l2: 0},
|
|
56
|
+
FRONT: {l1: 750, l2: 0},
|
|
57
|
+
CLAIM: {l1: 10000, l2: 0}
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
readonly chainId = "STARKNET";
|
|
@@ -192,12 +192,6 @@ export class StarknetSpvVaultContract
|
|
|
192
192
|
return vaults;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
async getFronterAddress(owner: string, vaultId: bigint, withdrawal: StarknetSpvWithdrawalData): Promise<string | null> {
|
|
196
|
-
const fronterAddress = await this.contract.get_fronter_address_by_id(owner, vaultId, "0x"+withdrawal.getFrontingId());
|
|
197
|
-
if(toHex(fronterAddress, 64)==="0x0000000000000000000000000000000000000000000000000000000000000000") return null;
|
|
198
|
-
return fronterAddress;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
195
|
async getWithdrawalState(btcTxId: string): Promise<SpvWithdrawalState> {
|
|
202
196
|
const txHash = Buffer.from(btcTxId, "hex").reverse();
|
|
203
197
|
const txHashU256 = cairo.uint256("0x"+txHash.toString("hex"));
|
|
@@ -470,14 +464,14 @@ export class StarknetSpvVaultContract
|
|
|
470
464
|
return [await action.tx(feeRate)];
|
|
471
465
|
}
|
|
472
466
|
|
|
473
|
-
async getClaimFee(signer: string,
|
|
467
|
+
async getClaimFee(signer: string, withdrawalData: StarknetSpvWithdrawalData, feeRate?: string): Promise<bigint> {
|
|
474
468
|
feeRate ??= await this.Chain.Fees.getFeeRate();
|
|
475
|
-
return StarknetFees.getGasFee(StarknetSpvVaultContract.GasCosts.CLAIM, feeRate);
|
|
469
|
+
return StarknetFees.getGasFee(StarknetSpvVaultContract.GasCosts.CLAIM.l1, feeRate);
|
|
476
470
|
}
|
|
477
471
|
|
|
478
|
-
async getFrontFee(signer: string,
|
|
472
|
+
async getFrontFee(signer: string, withdrawalData: StarknetSpvWithdrawalData, feeRate?: string): Promise<bigint> {
|
|
479
473
|
feeRate ??= await this.Chain.Fees.getFeeRate();
|
|
480
|
-
return StarknetFees.getGasFee(StarknetSpvVaultContract.GasCosts.FRONT, feeRate);
|
|
474
|
+
return StarknetFees.getGasFee(StarknetSpvVaultContract.GasCosts.FRONT.l1, feeRate);
|
|
481
475
|
}
|
|
482
476
|
|
|
483
477
|
}
|
|
@@ -148,7 +148,6 @@ export class StarknetSpvVaultData extends SpvVaultData<StarknetSpvWithdrawalData
|
|
|
148
148
|
utxo: this.utxo,
|
|
149
149
|
confirmations: this.confirmations,
|
|
150
150
|
withdrawCount: this.withdrawCount,
|
|
151
|
-
depositCount: this.depositCount,
|
|
152
151
|
initialUtxo: this.initialUtxo
|
|
153
152
|
}
|
|
154
153
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {SpvWithdrawalTransactionData} from "@atomiqlabs/base";
|
|
2
2
|
import {Buffer} from "buffer";
|
|
3
|
-
import {BigNumberish, cairo
|
|
3
|
+
import {BigNumberish, cairo} from "starknet";
|
|
4
4
|
import {toBigInt} from "../../utils/Utils";
|
|
5
5
|
import {StarknetSpvVaultContract} from "./StarknetSpvVaultContract";
|
|
6
6
|
|
|
@@ -63,17 +63,6 @@ export class StarknetSpvWithdrawalData extends SpvWithdrawalTransactionData {
|
|
|
63
63
|
]
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
getFrontingId(): string {
|
|
67
|
-
const txHashU256 = cairo.uint256(BigIntBufferUtils.fromBuffer(Buffer.from(this.btcTx.txid), "le"));
|
|
68
|
-
let frontingId = hash.computePoseidonHashOnElements([
|
|
69
|
-
txHashU256.low,
|
|
70
|
-
txHashU256.high,
|
|
71
|
-
...this.serializeToFelts()
|
|
72
|
-
]);
|
|
73
|
-
if(frontingId.startsWith("0x")) frontingId = frontingId.slice(2);
|
|
74
|
-
return frontingId.padStart(64, "0");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
66
|
}
|
|
78
67
|
|
|
79
68
|
SpvWithdrawalTransactionData.deserializers["STARKNET"] = StarknetSpvWithdrawalData;
|
|
@@ -18,38 +18,6 @@ export const EscrowManagerAbi = [
|
|
|
18
18
|
}
|
|
19
19
|
]
|
|
20
20
|
},
|
|
21
|
-
{
|
|
22
|
-
"type": "struct",
|
|
23
|
-
"name": "escrow_manager::structs::escrow::EscrowExecution",
|
|
24
|
-
"members": [
|
|
25
|
-
{
|
|
26
|
-
"name": "hash",
|
|
27
|
-
"type": "core::felt252"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"name": "expiry",
|
|
31
|
-
"type": "core::integer::u64"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"name": "fee",
|
|
35
|
-
"type": "core::integer::u256"
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"type": "enum",
|
|
41
|
-
"name": "core::option::Option::<escrow_manager::structs::escrow::EscrowExecution>",
|
|
42
|
-
"variants": [
|
|
43
|
-
{
|
|
44
|
-
"name": "Some",
|
|
45
|
-
"type": "escrow_manager::structs::escrow::EscrowExecution"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"name": "None",
|
|
49
|
-
"type": "()"
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
},
|
|
53
21
|
{
|
|
54
22
|
"type": "struct",
|
|
55
23
|
"name": "escrow_manager::structs::escrow::EscrowData",
|
|
@@ -101,10 +69,6 @@ export const EscrowManagerAbi = [
|
|
|
101
69
|
{
|
|
102
70
|
"name": "claimer_bounty",
|
|
103
71
|
"type": "core::integer::u256"
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
"name": "success_action",
|
|
107
|
-
"type": "core::option::Option::<escrow_manager::structs::escrow::EscrowExecution>"
|
|
108
72
|
}
|
|
109
73
|
]
|
|
110
74
|
},
|
|
@@ -14,7 +14,7 @@ import {EscrowManagerAbi} from "./EscrowManagerAbi";
|
|
|
14
14
|
import {StarknetContractBase} from "../contract/StarknetContractBase";
|
|
15
15
|
import {StarknetTx} from "../chain/modules/StarknetTransactions";
|
|
16
16
|
import {StarknetSigner} from "../wallet/StarknetSigner";
|
|
17
|
-
import {BigNumberish, constants} from "starknet";
|
|
17
|
+
import {BigNumberish, constants, logger} from "starknet";
|
|
18
18
|
import {StarknetChainInterface} from "../chain/StarknetChainInterface";
|
|
19
19
|
import {StarknetBtcRelay} from "../btcrelay/StarknetBtcRelay";
|
|
20
20
|
import {StarknetSwapData} from "./StarknetSwapData";
|
|
@@ -34,8 +34,8 @@ const ESCROW_STATE_CLAIMED = 2;
|
|
|
34
34
|
const ESCROW_STATE_REFUNDED = 3;
|
|
35
35
|
|
|
36
36
|
const swapContractAddreses = {
|
|
37
|
-
[constants.StarknetChainId.SN_SEPOLIA]: "
|
|
38
|
-
[constants.StarknetChainId.SN_MAIN]: "
|
|
37
|
+
[constants.StarknetChainId.SN_SEPOLIA]: "0x06874044dae5bbe712775cdb576d6aef45fc87a22ce629f2b101a7d591d4e7ca",
|
|
38
|
+
[constants.StarknetChainId.SN_MAIN]: "0x04fb26d02d2cf612566cd86cab299716d926272e9f49514670233952ecaf8f0c"
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
const defaultClaimAddresses = {
|
|
@@ -73,8 +73,6 @@ export class StarknetSwapContract
|
|
|
73
73
|
"STARKNET"
|
|
74
74
|
> {
|
|
75
75
|
|
|
76
|
-
readonly supportsInitWithoutClaimer = true;
|
|
77
|
-
|
|
78
76
|
////////////////////////
|
|
79
77
|
//// Constants
|
|
80
78
|
readonly chainId: "STARKNET" = "STARKNET";
|
|
@@ -134,7 +132,7 @@ export class StarknetSwapContract
|
|
|
134
132
|
|
|
135
133
|
claimHandlersList.forEach(handlerCtor => {
|
|
136
134
|
const handler = new handlerCtor(handlerAddresses.claim[handlerCtor.type]);
|
|
137
|
-
this.claimHandlersByAddress[
|
|
135
|
+
this.claimHandlersByAddress[handler.address] = handler;
|
|
138
136
|
this.claimHandlersBySwapType[handlerCtor.type] = handler;
|
|
139
137
|
});
|
|
140
138
|
|
|
@@ -329,6 +327,23 @@ export class StarknetSwapContract
|
|
|
329
327
|
blockHeight, blockHeight
|
|
330
328
|
);
|
|
331
329
|
return events.length===0 ? null : events[0].txHash;
|
|
330
|
+
},
|
|
331
|
+
getClaimResult: async () => {
|
|
332
|
+
const events = await this.Events.getContractBlockEvents(
|
|
333
|
+
["escrow_manager::events::Claim"],
|
|
334
|
+
[null, null, null, "0x"+escrowHash],
|
|
335
|
+
blockHeight, blockHeight
|
|
336
|
+
);
|
|
337
|
+
if(events.length===0) return null;
|
|
338
|
+
const event = events[0];
|
|
339
|
+
const claimHandlerHex = toHex(event.params.claim_handler);
|
|
340
|
+
const claimHandler = this.claimHandlersByAddress[claimHandlerHex];
|
|
341
|
+
if(claimHandler==null) {
|
|
342
|
+
logger.warn("getCommitStatus(): getClaimResult("+escrowHash+"): Unknown claim handler with claim: "+claimHandlerHex);
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const witnessResult = claimHandler.parseWitnessResult(event.params.witness_result);
|
|
346
|
+
return witnessResult;
|
|
332
347
|
}
|
|
333
348
|
};
|
|
334
349
|
default:
|
|
@@ -616,14 +631,14 @@ export class StarknetSwapContract
|
|
|
616
631
|
/**
|
|
617
632
|
* Get the estimated solana fee of the commit transaction
|
|
618
633
|
*/
|
|
619
|
-
getCommitFee(
|
|
634
|
+
getCommitFee(swapData: StarknetSwapData, feeRate?: string): Promise<bigint> {
|
|
620
635
|
return this.Init.getInitFee(swapData, feeRate);
|
|
621
636
|
}
|
|
622
637
|
|
|
623
638
|
/**
|
|
624
639
|
* Get the estimated solana transaction fee of the refund transaction
|
|
625
640
|
*/
|
|
626
|
-
getRefundFee(
|
|
641
|
+
getRefundFee(swapData: StarknetSwapData, feeRate?: string): Promise<bigint> {
|
|
627
642
|
return this.Refund.getRefundFee(swapData, feeRate);
|
|
628
643
|
}
|
|
629
644
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {SwapData, ChainSwapType} from "@atomiqlabs/base";
|
|
2
2
|
import {TimelockRefundHandler} from "./handlers/refund/TimelockRefundHandler";
|
|
3
|
-
import {BigNumberish, cairo,
|
|
3
|
+
import {BigNumberish, cairo, hash} from "starknet";
|
|
4
4
|
import {toBigInt, toHex} from "../../utils/Utils";
|
|
5
5
|
import {
|
|
6
6
|
StringToPrimitiveType
|
|
@@ -14,21 +14,6 @@ const FLAG_REPUTATION: bigint = 0x04n;
|
|
|
14
14
|
|
|
15
15
|
export type StarknetSwapDataType = StringToPrimitiveType<typeof EscrowManagerAbi, "escrow_manager::structs::escrow::EscrowData">;
|
|
16
16
|
|
|
17
|
-
export type StarknetSuccessAction = {
|
|
18
|
-
executionHash: string,
|
|
19
|
-
executionExpiry: bigint,
|
|
20
|
-
executionFee: bigint
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function successActionEquals(a: StarknetSuccessAction, b: StarknetSuccessAction): boolean {
|
|
24
|
-
if(a!=null && b!=null) {
|
|
25
|
-
return a.executionHash.toLowerCase()===b.executionHash.toLowerCase() &&
|
|
26
|
-
a.executionExpiry === b.executionExpiry &&
|
|
27
|
-
a.executionFee === b.executionFee;
|
|
28
|
-
}
|
|
29
|
-
return a === b;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
17
|
export class StarknetSwapData extends SwapData {
|
|
33
18
|
|
|
34
19
|
static toFlags(value: number | bigint | string): {payOut: boolean, payIn: boolean, reputation: boolean, sequence: bigint} {
|
|
@@ -72,8 +57,6 @@ export class StarknetSwapData extends SwapData {
|
|
|
72
57
|
|
|
73
58
|
extraData: string;
|
|
74
59
|
|
|
75
|
-
successAction?: StarknetSuccessAction;
|
|
76
|
-
|
|
77
60
|
kind: ChainSwapType;
|
|
78
61
|
|
|
79
62
|
constructor(
|
|
@@ -93,8 +76,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
93
76
|
securityDeposit: bigint,
|
|
94
77
|
claimerBounty: bigint,
|
|
95
78
|
kind: ChainSwapType,
|
|
96
|
-
extraData: string
|
|
97
|
-
successAction?: StarknetSuccessAction
|
|
79
|
+
extraData: string
|
|
98
80
|
);
|
|
99
81
|
|
|
100
82
|
constructor(data: any);
|
|
@@ -116,8 +98,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
116
98
|
securityDeposit?: bigint,
|
|
117
99
|
claimerBounty?: bigint,
|
|
118
100
|
kind?: ChainSwapType,
|
|
119
|
-
extraData?: string
|
|
120
|
-
successAction?: StarknetSuccessAction
|
|
101
|
+
extraData?: string
|
|
121
102
|
) {
|
|
122
103
|
super();
|
|
123
104
|
if(claimer!=null || token!=null || refundHandler!=null || claimHandler!=null ||
|
|
@@ -140,7 +121,6 @@ export class StarknetSwapData extends SwapData {
|
|
|
140
121
|
this.claimerBounty = claimerBounty;
|
|
141
122
|
this.kind = kind;
|
|
142
123
|
this.extraData = extraData;
|
|
143
|
-
this.successAction = successAction;
|
|
144
124
|
} else {
|
|
145
125
|
this.offerer = offererOrData.offerer;
|
|
146
126
|
this.claimer = offererOrData.claimer;
|
|
@@ -159,11 +139,6 @@ export class StarknetSwapData extends SwapData {
|
|
|
159
139
|
this.claimerBounty = offererOrData.claimerBounty==null ? null : BigInt(offererOrData.claimerBounty);
|
|
160
140
|
this.kind = offererOrData.kind;
|
|
161
141
|
this.extraData = offererOrData.extraData;
|
|
162
|
-
this.successAction = offererOrData.successAction==null ? null : {
|
|
163
|
-
executionHash: offererOrData.successAction.executionHash,
|
|
164
|
-
executionExpiry: BigInt(offererOrData.successAction.executionExpiry),
|
|
165
|
-
executionFee: BigInt(offererOrData.successAction.executionFee),
|
|
166
|
-
}
|
|
167
142
|
}
|
|
168
143
|
}
|
|
169
144
|
|
|
@@ -206,12 +181,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
206
181
|
securityDeposit: this.securityDeposit==null ? null : this.securityDeposit.toString(10),
|
|
207
182
|
claimerBounty: this.claimerBounty==null ? null : this.claimerBounty.toString(10),
|
|
208
183
|
kind: this.kind,
|
|
209
|
-
extraData: this.extraData
|
|
210
|
-
successAction: this.successAction==null ? null : {
|
|
211
|
-
executionHash: this.successAction.executionHash,
|
|
212
|
-
executionExpiry: this.successAction.executionExpiry.toString(10),
|
|
213
|
-
executionFee: this.successAction.executionFee.toString(10)
|
|
214
|
-
}
|
|
184
|
+
extraData: this.extraData
|
|
215
185
|
}
|
|
216
186
|
}
|
|
217
187
|
|
|
@@ -247,7 +217,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
247
217
|
const amountValue = cairo.uint256("0x"+this.amount.toString(16));
|
|
248
218
|
const securityDepositValue = cairo.uint256("0x"+this.securityDeposit.toString(16));
|
|
249
219
|
const claimerBountyValue = cairo.uint256("0x"+this.claimerBounty.toString(16));
|
|
250
|
-
|
|
220
|
+
let escrowHash = hash.computePoseidonHashOnElements([
|
|
251
221
|
this.offerer,
|
|
252
222
|
this.claimer,
|
|
253
223
|
this.token,
|
|
@@ -263,15 +233,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
263
233
|
securityDepositValue.high,
|
|
264
234
|
claimerBountyValue.low,
|
|
265
235
|
claimerBountyValue.high
|
|
266
|
-
];
|
|
267
|
-
if(this.successAction!=null) {
|
|
268
|
-
elements.push(this.successAction.executionHash);
|
|
269
|
-
elements.push(this.successAction.executionExpiry);
|
|
270
|
-
const feeValue = cairo.uint256("0x"+this.successAction.executionFee.toString(16));
|
|
271
|
-
elements.push(feeValue.low, feeValue.high);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
let escrowHash = hash.computePoseidonHashOnElements(elements);
|
|
236
|
+
]);
|
|
275
237
|
if(escrowHash.startsWith("0x")) escrowHash = escrowHash.slice(2);
|
|
276
238
|
return escrowHash.padStart(64, "0");
|
|
277
239
|
}
|
|
@@ -372,8 +334,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
372
334
|
other.refundData.toLowerCase()===this.refundData.toLowerCase() &&
|
|
373
335
|
other.amount === this.amount &&
|
|
374
336
|
other.securityDeposit === this.securityDeposit &&
|
|
375
|
-
other.claimerBounty === this.claimerBounty
|
|
376
|
-
successActionEquals(other.successAction, this.successAction)
|
|
337
|
+
other.claimerBounty === this.claimerBounty
|
|
377
338
|
}
|
|
378
339
|
|
|
379
340
|
toEscrowStruct(): StarknetSwapDataType {
|
|
@@ -389,15 +350,7 @@ export class StarknetSwapData extends SwapData {
|
|
|
389
350
|
amount: cairo.uint256(toBigInt(this.amount)),
|
|
390
351
|
fee_token: this.feeToken,
|
|
391
352
|
security_deposit: cairo.uint256(toBigInt(this.securityDeposit)),
|
|
392
|
-
claimer_bounty: cairo.uint256(toBigInt(this.claimerBounty))
|
|
393
|
-
success_action: new CairoOption(
|
|
394
|
-
this.successAction==null ? CairoOptionVariant.None : CairoOptionVariant.Some,
|
|
395
|
-
this.successAction==null ? undefined : {
|
|
396
|
-
hash: this.successAction.executionHash,
|
|
397
|
-
expiry: this.successAction.executionExpiry,
|
|
398
|
-
fee: cairo.uint256(this.successAction.executionFee)
|
|
399
|
-
}
|
|
400
|
-
) as StarknetSwapDataType["success_action"]
|
|
353
|
+
claimer_bounty: cairo.uint256(toBigInt(this.claimerBounty))
|
|
401
354
|
}
|
|
402
355
|
}
|
|
403
356
|
|
|
@@ -414,15 +367,6 @@ export class StarknetSwapData extends SwapData {
|
|
|
414
367
|
const feeToken = toHex(span.shift());
|
|
415
368
|
const securityDeposit = toBigInt({low: span.shift(), high: span.shift()});
|
|
416
369
|
const claimerBounty = toBigInt({low: span.shift(), high: span.shift()});
|
|
417
|
-
const hasSuccessAction = toBigInt(span.shift()) === 0n;
|
|
418
|
-
let successAction: StarknetSuccessAction = null;
|
|
419
|
-
if(hasSuccessAction) {
|
|
420
|
-
successAction = {
|
|
421
|
-
executionHash: toHex(span.shift()),
|
|
422
|
-
executionExpiry: toBigInt(span.shift()),
|
|
423
|
-
executionFee: toBigInt({low: span.shift(), high: span.shift()})
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
370
|
|
|
427
371
|
return new StarknetSwapData(
|
|
428
372
|
offerer,
|
|
@@ -441,15 +385,10 @@ export class StarknetSwapData extends SwapData {
|
|
|
441
385
|
securityDeposit,
|
|
442
386
|
claimerBounty,
|
|
443
387
|
claimHandlerImpl.getType(),
|
|
444
|
-
null
|
|
445
|
-
successAction
|
|
388
|
+
null
|
|
446
389
|
);
|
|
447
390
|
}
|
|
448
391
|
|
|
449
|
-
hasSuccessAction(): boolean {
|
|
450
|
-
return this.successAction != null;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
392
|
}
|
|
454
393
|
|
|
455
394
|
SwapData.deserializers["strk"] = StarknetSwapData;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {StarknetSwapData} from "../StarknetSwapData";
|
|
2
2
|
import {BigNumberish} from "starknet";
|
|
3
|
+
import {StarknetGas} from "../../chain/StarknetAction";
|
|
3
4
|
import {StarknetTx} from "../../chain/modules/StarknetTransactions";
|
|
4
|
-
import {StarknetGas} from "../../chain/modules/StarknetFees";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
export interface IHandler<TCommitmentData, TWitnessData> {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {HashlockClaimHandler} from "./HashlockClaimHandler";
|
|
2
2
|
import {ChainSwapType} from "@atomiqlabs/base";
|
|
3
|
+
import {StarknetGas} from "../../../chain/StarknetAction";
|
|
3
4
|
import {IHandler} from "../IHandler";
|
|
4
5
|
import {BitcoinTxIdClaimHandler} from "./btc/BitcoinTxIdClaimHandler";
|
|
5
6
|
import {BitcoinOutputClaimHandler} from "./btc/BitcoinOutputClaimHandler";
|
|
6
7
|
import {BitcoinNoncedOutputClaimHandler} from "./btc/BitcoinNoncedOutputClaimHandler";
|
|
7
8
|
import {BigNumberish} from "starknet";
|
|
8
|
-
import {StarknetGas} from "../../../chain/modules/StarknetFees";
|
|
9
9
|
|
|
10
10
|
export interface IClaimHandler<C, W> extends IHandler<C, W> {
|
|
11
11
|
getType(): ChainSwapType;
|
|
@@ -2,17 +2,17 @@ import {StarknetSwapData} from "../../StarknetSwapData";
|
|
|
2
2
|
import {bufferToU32Array, toHex, u32ArrayToBuffer} from "../../../../utils/Utils";
|
|
3
3
|
import {BigNumberish, hash} from "starknet";
|
|
4
4
|
import {ChainSwapType} from "@atomiqlabs/base";
|
|
5
|
+
import {StarknetGas} from "../../../chain/StarknetAction";
|
|
5
6
|
import {Buffer} from "buffer";
|
|
6
7
|
import {sha256} from "@noble/hashes/sha2";
|
|
7
8
|
import {StarknetTx} from "../../../chain/modules/StarknetTransactions";
|
|
8
9
|
import {IClaimHandler} from "./ClaimHandlers";
|
|
9
|
-
import {StarknetGas} from "../../../chain/modules/StarknetFees";
|
|
10
10
|
|
|
11
11
|
export class HashlockClaimHandler implements IClaimHandler<Buffer, string> {
|
|
12
12
|
|
|
13
13
|
public readonly address: string;
|
|
14
14
|
public static readonly type: ChainSwapType = ChainSwapType.HTLC;
|
|
15
|
-
public static readonly gas: StarknetGas = {
|
|
15
|
+
public static readonly gas: StarknetGas = {l1: 750};
|
|
16
16
|
|
|
17
17
|
constructor(address: string) {
|
|
18
18
|
this.address = address;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {StarknetSwapData} from "../../../StarknetSwapData";
|
|
2
|
+
import {StarknetGas} from "../../../../chain/StarknetAction";
|
|
2
3
|
import {ChainSwapType} from "@atomiqlabs/base";
|
|
3
4
|
import {BigNumberish, hash} from "starknet";
|
|
4
5
|
import {StarknetTx} from "../../../../chain/modules/StarknetTransactions";
|
|
@@ -7,7 +8,6 @@ import {BitcoinCommitmentData, IBitcoinClaimHandler} from "./IBitcoinClaimHandle
|
|
|
7
8
|
import {BitcoinOutputWitnessData} from "./BitcoinOutputClaimHandler";
|
|
8
9
|
import {Transaction} from "@scure/btc-signer";
|
|
9
10
|
import {Buffer} from "buffer";
|
|
10
|
-
import {StarknetGas} from "../../../../chain/modules/StarknetFees";
|
|
11
11
|
|
|
12
12
|
export type BitcoinNoncedOutputCommitmentData = {
|
|
13
13
|
output: Buffer,
|
|
@@ -27,7 +27,7 @@ function getTransactionNonce(btcTx: Transaction): bigint {
|
|
|
27
27
|
export class BitcoinNoncedOutputClaimHandler extends IBitcoinClaimHandler<BitcoinNoncedOutputCommitmentData, BitcoinOutputWitnessData> {
|
|
28
28
|
|
|
29
29
|
public static readonly type: ChainSwapType = ChainSwapType.CHAIN_NONCED;
|
|
30
|
-
public static readonly gas: StarknetGas = {
|
|
30
|
+
public static readonly gas: StarknetGas = {l1: 20000};
|
|
31
31
|
|
|
32
32
|
protected serializeCommitment(data: BitcoinNoncedOutputCommitmentData & BitcoinCommitmentData): BigNumberish[] {
|
|
33
33
|
return [
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {StarknetSwapData} from "../../../StarknetSwapData";
|
|
2
|
+
import {StarknetGas} from "../../../../chain/StarknetAction";
|
|
2
3
|
import {ChainSwapType} from "@atomiqlabs/base";
|
|
3
4
|
import {BigNumberish, hash} from "starknet";
|
|
4
5
|
import {StarknetTx} from "../../../../chain/modules/StarknetTransactions";
|
|
@@ -6,7 +7,6 @@ import {bufferToByteArray, getLogger, poseidonHashRange, toBigInt} from "../../.
|
|
|
6
7
|
import {BitcoinCommitmentData, BitcoinWitnessData, IBitcoinClaimHandler} from "./IBitcoinClaimHandler";
|
|
7
8
|
import {Transaction} from "@scure/btc-signer";
|
|
8
9
|
import {Buffer} from "buffer";
|
|
9
|
-
import {StarknetGas} from "../../../../chain/modules/StarknetFees";
|
|
10
10
|
|
|
11
11
|
export type BitcoinOutputCommitmentData = {
|
|
12
12
|
output: Buffer,
|
|
@@ -22,7 +22,7 @@ const logger = getLogger("BitcoinOutputClaimHandler: ");
|
|
|
22
22
|
export class BitcoinOutputClaimHandler extends IBitcoinClaimHandler<BitcoinOutputCommitmentData, BitcoinOutputWitnessData> {
|
|
23
23
|
|
|
24
24
|
public static readonly type: ChainSwapType = ChainSwapType.CHAIN;
|
|
25
|
-
public static readonly gas: StarknetGas = {
|
|
25
|
+
public static readonly gas: StarknetGas = {l1: 20000};
|
|
26
26
|
|
|
27
27
|
protected serializeCommitment(data: BitcoinOutputCommitmentData & BitcoinCommitmentData): BigNumberish[] {
|
|
28
28
|
return [
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {StarknetSwapData} from "../../../StarknetSwapData";
|
|
2
|
+
import {StarknetGas} from "../../../../chain/StarknetAction";
|
|
2
3
|
import {ChainSwapType} from "@atomiqlabs/base";
|
|
3
4
|
import {BigNumberish} from "starknet";
|
|
4
5
|
import {StarknetTx} from "../../../../chain/modules/StarknetTransactions";
|
|
5
6
|
import {bufferToU32Array, getLogger} from "../../../../../utils/Utils";
|
|
6
7
|
import {BitcoinCommitmentData, BitcoinWitnessData, IBitcoinClaimHandler} from "./IBitcoinClaimHandler";
|
|
7
8
|
import {Buffer} from "buffer";
|
|
8
|
-
import {StarknetGas} from "../../../../chain/modules/StarknetFees";
|
|
9
9
|
|
|
10
10
|
export type BitcoinTxIdCommitmentData = {
|
|
11
11
|
txId: string
|
|
@@ -16,7 +16,7 @@ const logger = getLogger("BitcoinTxIdClaimHandler: ");
|
|
|
16
16
|
export class BitcoinTxIdClaimHandler extends IBitcoinClaimHandler<BitcoinTxIdCommitmentData, BitcoinWitnessData> {
|
|
17
17
|
|
|
18
18
|
public static readonly type: ChainSwapType = ChainSwapType.CHAIN_TXID;
|
|
19
|
-
public static readonly gas: StarknetGas = {
|
|
19
|
+
public static readonly gas: StarknetGas = {l1: 20000};
|
|
20
20
|
|
|
21
21
|
protected serializeCommitment(data: BitcoinTxIdCommitmentData & BitcoinCommitmentData): BigNumberish[] {
|
|
22
22
|
return [
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {IClaimHandler} from "../ClaimHandlers";
|
|
2
2
|
import {StarknetSwapData} from "../../../StarknetSwapData";
|
|
3
|
+
import {StarknetGas} from "../../../../chain/StarknetAction";
|
|
3
4
|
import {ChainSwapType, RelaySynchronizer} from "@atomiqlabs/base";
|
|
4
5
|
import {BigNumberish, hash} from "starknet";
|
|
5
6
|
import {StarknetBtcStoredHeader} from "../../../../btcrelay/headers/StarknetBtcStoredHeader";
|
|
6
7
|
import {StarknetTx} from "../../../../chain/modules/StarknetTransactions";
|
|
7
8
|
import {StarknetBtcRelay} from "../../../../btcrelay/StarknetBtcRelay";
|
|
8
9
|
import {bufferToU32Array, getLogger, u32ArrayToBuffer} from "../../../../../utils/Utils";
|
|
9
|
-
import {StarknetGas} from "../../../../chain/modules/StarknetFees";
|
|
10
10
|
|
|
11
11
|
export type BitcoinCommitmentData = {
|
|
12
12
|
btcRelay: StarknetBtcRelay<any>,
|
|
@@ -33,7 +33,7 @@ export abstract class IBitcoinClaimHandler<C, W extends BitcoinWitnessData> impl
|
|
|
33
33
|
|
|
34
34
|
public static readonly address = "";
|
|
35
35
|
public static readonly type: ChainSwapType = ChainSwapType.CHAIN_TXID;
|
|
36
|
-
public static readonly gas: StarknetGas = {
|
|
36
|
+
public static readonly gas: StarknetGas = {l1: 20000};
|
|
37
37
|
|
|
38
38
|
protected serializeCommitment(data: BitcoinCommitmentData): BigNumberish[] {
|
|
39
39
|
return [
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {StarknetTx} from "../../../chain/modules/StarknetTransactions";
|
|
2
2
|
import {StarknetSwapData} from "../../StarknetSwapData";
|
|
3
|
-
import {bigNumberishToBuffer} from "../../../../utils/Utils";
|
|
3
|
+
import {bigNumberishToBuffer, toBigInt} from "../../../../utils/Utils";
|
|
4
4
|
import {BigNumberish} from "starknet";
|
|
5
5
|
import {IHandler} from "../IHandler";
|
|
6
|
-
import {StarknetGas} from "../../../chain/
|
|
6
|
+
import {StarknetGas} from "../../../chain/StarknetAction";
|
|
7
7
|
|
|
8
8
|
export class TimelockRefundHandler implements IHandler<bigint, never> {
|
|
9
9
|
|
|
10
10
|
public readonly address: string;
|
|
11
|
-
public static readonly gas: StarknetGas = {
|
|
11
|
+
public static readonly gas: StarknetGas = {l1: 500};
|
|
12
12
|
|
|
13
13
|
constructor(address: string) {
|
|
14
14
|
this.address = address;
|
|
@@ -8,8 +8,8 @@ import {StarknetTx} from "../../chain/modules/StarknetTransactions";
|
|
|
8
8
|
export class StarknetLpVault extends StarknetSwapModule {
|
|
9
9
|
|
|
10
10
|
private static readonly GasCosts = {
|
|
11
|
-
WITHDRAW: {
|
|
12
|
-
DEPOSIT: {l1:
|
|
11
|
+
WITHDRAW: {l1: 750, l2: 0},
|
|
12
|
+
DEPOSIT: {l1: 750, l2: 0}
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -2,11 +2,11 @@ import {ChainSwapType, RelaySynchronizer, SwapDataVerificationError} from "@atom
|
|
|
2
2
|
import {toHex} from "../../../utils/Utils";
|
|
3
3
|
import {StarknetSwapModule} from "../StarknetSwapModule";
|
|
4
4
|
import {StarknetSwapData} from "../StarknetSwapData";
|
|
5
|
-
import {StarknetAction} from "../../chain/StarknetAction";
|
|
5
|
+
import {StarknetAction, StarknetGas, sumStarknetGas} from "../../chain/StarknetAction";
|
|
6
6
|
import {BigNumberish} from "starknet";
|
|
7
7
|
import {IClaimHandler} from "../handlers/claim/ClaimHandlers";
|
|
8
8
|
import {StarknetTx} from "../../chain/modules/StarknetTransactions";
|
|
9
|
-
import {StarknetFees
|
|
9
|
+
import {StarknetFees} from "../../chain/modules/StarknetFees";
|
|
10
10
|
import {StarknetBtcStoredHeader} from "../../btcrelay/headers/StarknetBtcStoredHeader";
|
|
11
11
|
import {BitcoinOutputWitnessData} from "../handlers/claim/btc/BitcoinOutputClaimHandler";
|
|
12
12
|
import {BitcoinWitnessData} from "../handlers/claim/btc/IBitcoinClaimHandler";
|
|
@@ -15,8 +15,8 @@ import {Buffer} from "buffer";
|
|
|
15
15
|
export class StarknetSwapClaim extends StarknetSwapModule {
|
|
16
16
|
|
|
17
17
|
private static readonly GasCosts = {
|
|
18
|
-
CLAIM: {
|
|
19
|
-
CLAIM_PAY_OUT: {
|
|
18
|
+
CLAIM: {l1: 500, l2: 0},
|
|
19
|
+
CLAIM_PAY_OUT: {l1: 1000, l2: 0}
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -37,7 +37,7 @@ export class StarknetSwapClaim extends StarknetSwapModule {
|
|
|
37
37
|
): StarknetAction {
|
|
38
38
|
return new StarknetAction(signer, this.root,
|
|
39
39
|
this.swapContract.populateTransaction.claim(swapData.toEscrowStruct(), witness),
|
|
40
|
-
|
|
40
|
+
sumStarknetGas(swapData.payOut ? StarknetSwapClaim.GasCosts.CLAIM_PAY_OUT : StarknetSwapClaim.GasCosts.CLAIM, claimHandlerGas)
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -64,7 +64,7 @@ export class StarknetSwapClaim extends StarknetSwapModule {
|
|
|
64
64
|
throw new SwapDataVerificationError("Not enough time to reliably pay the invoice");
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
const claimHandler: IClaimHandler<Buffer, string> = this.contract.claimHandlersByAddress[
|
|
67
|
+
const claimHandler: IClaimHandler<Buffer, string> = this.contract.claimHandlersByAddress[swapData.claimHandler.toLowerCase()];
|
|
68
68
|
if(claimHandler==null) throw new SwapDataVerificationError("Unknown claim handler!");
|
|
69
69
|
if(claimHandler.getType()!==ChainSwapType.HTLC) throw new SwapDataVerificationError("Invalid claim handler!");
|
|
70
70
|
|
|
@@ -101,7 +101,7 @@ export class StarknetSwapClaim extends StarknetSwapModule {
|
|
|
101
101
|
synchronizer?: RelaySynchronizer<StarknetBtcStoredHeader, StarknetTx, any>,
|
|
102
102
|
feeRate?: string
|
|
103
103
|
): Promise<StarknetTx[] | null> {
|
|
104
|
-
const claimHandler: IClaimHandler<any, BitcoinOutputWitnessData | BitcoinWitnessData> = this.contract.claimHandlersByAddress[
|
|
104
|
+
const claimHandler: IClaimHandler<any, BitcoinOutputWitnessData | BitcoinWitnessData> = this.contract.claimHandlersByAddress[swapData.claimHandler.toLowerCase()];
|
|
105
105
|
if(claimHandler==null) throw new SwapDataVerificationError("Unknown claim handler!");
|
|
106
106
|
if(
|
|
107
107
|
claimHandler.getType()!==ChainSwapType.CHAIN_NONCED &&
|
|
@@ -133,10 +133,10 @@ export class StarknetSwapClaim extends StarknetSwapModule {
|
|
|
133
133
|
|
|
134
134
|
let gasRequired = swapData.payOut ? StarknetSwapClaim.GasCosts.CLAIM_PAY_OUT : StarknetSwapClaim.GasCosts.CLAIM;
|
|
135
135
|
|
|
136
|
-
const claimHandler: IClaimHandler<any, any> = this.contract.claimHandlersByAddress[
|
|
137
|
-
if(claimHandler!=null) gasRequired =
|
|
136
|
+
const claimHandler: IClaimHandler<any, any> = this.contract.claimHandlersByAddress[swapData.claimHandler.toLowerCase()];
|
|
137
|
+
if(claimHandler!=null) gasRequired = sumStarknetGas(gasRequired, claimHandler.getGas(swapData));
|
|
138
138
|
|
|
139
|
-
return StarknetFees.getGasFee(gasRequired, feeRate);
|
|
139
|
+
return StarknetFees.getGasFee(gasRequired.l1, feeRate);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
}
|