@toon-protocol/client 0.18.0 → 0.19.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/README.md +19 -24
- package/dist/index.d.ts +442 -4
- package/dist/index.js +421 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3409,7 +3409,14 @@ async function buildMinaPaymentChannelProof(params) {
|
|
|
3409
3409
|
}
|
|
3410
3410
|
|
|
3411
3411
|
// src/channel/mina-deposit.ts
|
|
3412
|
-
var
|
|
3412
|
+
var CHANNEL_STATE_INDEX = {
|
|
3413
|
+
channelHash: 0,
|
|
3414
|
+
balanceCommitment: 1,
|
|
3415
|
+
nonceField: 2,
|
|
3416
|
+
channelState: 3,
|
|
3417
|
+
depositTotal: 4
|
|
3418
|
+
};
|
|
3419
|
+
var DEPOSIT_TOTAL_STATE_INDEX = CHANNEL_STATE_INDEX.depositTotal;
|
|
3413
3420
|
async function readMinaDepositTotal(graphqlUrl, zkAppAddress, fetchImpl = fetch) {
|
|
3414
3421
|
const query = "query($pk:String!){account(publicKey:$pk){zkappState}}";
|
|
3415
3422
|
const res = await fetchImpl(graphqlUrl, {
|
|
@@ -3434,6 +3441,42 @@ async function readMinaDepositTotal(graphqlUrl, zkAppAddress, fetchImpl = fetch)
|
|
|
3434
3441
|
}
|
|
3435
3442
|
return BigInt(state[DEPOSIT_TOTAL_STATE_INDEX]);
|
|
3436
3443
|
}
|
|
3444
|
+
var MINA_CHANNEL_STATE = {
|
|
3445
|
+
UNINITIALIZED: 0,
|
|
3446
|
+
OPEN: 1,
|
|
3447
|
+
CLOSING: 2,
|
|
3448
|
+
SETTLED: 3
|
|
3449
|
+
};
|
|
3450
|
+
async function readMinaChannelState(graphqlUrl, zkAppAddress, fetchImpl = fetch) {
|
|
3451
|
+
const query = "query($pk:String!){account(publicKey:$pk){zkappState}}";
|
|
3452
|
+
const res = await fetchImpl(graphqlUrl, {
|
|
3453
|
+
method: "POST",
|
|
3454
|
+
headers: { "content-type": "application/json" },
|
|
3455
|
+
body: JSON.stringify({ query, variables: { pk: zkAppAddress } })
|
|
3456
|
+
});
|
|
3457
|
+
if (!res.ok) {
|
|
3458
|
+
throw new Error(`Mina GraphQL request failed: HTTP ${res.status}`);
|
|
3459
|
+
}
|
|
3460
|
+
const json = await res.json();
|
|
3461
|
+
if (json.errors && json.errors.length > 0) {
|
|
3462
|
+
throw new Error(
|
|
3463
|
+
`Mina GraphQL error: ${json.errors[0]?.message ?? "unknown"}`
|
|
3464
|
+
);
|
|
3465
|
+
}
|
|
3466
|
+
const state = json.data?.account?.zkappState;
|
|
3467
|
+
if (!state || state.length <= DEPOSIT_TOTAL_STATE_INDEX) {
|
|
3468
|
+
throw new Error(
|
|
3469
|
+
`Mina zkApp ${zkAppAddress} has no readable zkappState (account not found or not a zkApp)`
|
|
3470
|
+
);
|
|
3471
|
+
}
|
|
3472
|
+
return {
|
|
3473
|
+
channelHash: String(state[CHANNEL_STATE_INDEX.channelHash]),
|
|
3474
|
+
balanceCommitment: String(state[CHANNEL_STATE_INDEX.balanceCommitment]),
|
|
3475
|
+
nonceField: BigInt(state[CHANNEL_STATE_INDEX.nonceField]),
|
|
3476
|
+
channelState: Number(state[CHANNEL_STATE_INDEX.channelState]),
|
|
3477
|
+
depositTotal: BigInt(state[CHANNEL_STATE_INDEX.depositTotal])
|
|
3478
|
+
};
|
|
3479
|
+
}
|
|
3437
3480
|
|
|
3438
3481
|
// src/signing/mina-signer.ts
|
|
3439
3482
|
var DEFAULT_MINA_TOKEN_ID = "MINA";
|
|
@@ -4731,7 +4774,265 @@ async function submitEvmSettlement(bundle, params) {
|
|
|
4731
4774
|
}
|
|
4732
4775
|
}
|
|
4733
4776
|
|
|
4777
|
+
// src/swap/mina-settlement.ts
|
|
4778
|
+
import { hexToMinaBase58PrivateKey as hexToMinaBase58PrivateKey4 } from "@toon-protocol/core";
|
|
4779
|
+
var MinaSettlementError = class extends Error {
|
|
4780
|
+
code;
|
|
4781
|
+
constructor(code, message) {
|
|
4782
|
+
super(`${code}: ${message}`);
|
|
4783
|
+
this.name = "MinaSettlementError";
|
|
4784
|
+
this.code = code;
|
|
4785
|
+
}
|
|
4786
|
+
};
|
|
4787
|
+
function parseProofSignature(proofJson) {
|
|
4788
|
+
const parsed = JSON.parse(proofJson);
|
|
4789
|
+
const r = parsed.signature?.r;
|
|
4790
|
+
const s = parsed.signature?.s;
|
|
4791
|
+
if (typeof r !== "string" || typeof s !== "string") {
|
|
4792
|
+
throw new Error("recipient co-signature proof did not carry string r/s");
|
|
4793
|
+
}
|
|
4794
|
+
return { r, s };
|
|
4795
|
+
}
|
|
4796
|
+
async function buildMinaCoSignedClaim(inputs) {
|
|
4797
|
+
const channelNonce = inputs.channelNonce ?? 0n;
|
|
4798
|
+
const salt = inputs.saltOverride ?? deriveMinaSalt(inputs.channelId, Number(inputs.nonce));
|
|
4799
|
+
if (inputs.cumulativeAmount > inputs.depositTotal) {
|
|
4800
|
+
throw new MinaSettlementError(
|
|
4801
|
+
"CUMULATIVE_EXCEEDS_DEPOSIT",
|
|
4802
|
+
`claim cumulativeAmount (${inputs.cumulativeAmount}) exceeds the channel depositTotal (${inputs.depositTotal}) \u2014 cannot conserve balances`
|
|
4803
|
+
);
|
|
4804
|
+
}
|
|
4805
|
+
const { Poseidon, PublicKey } = await loadMinaPaymentChannelBindings();
|
|
4806
|
+
const hashRecipientFirst = minaParticipantChannelHashField(
|
|
4807
|
+
Poseidon,
|
|
4808
|
+
PublicKey,
|
|
4809
|
+
inputs.recipient,
|
|
4810
|
+
inputs.swapSignerAddress,
|
|
4811
|
+
channelNonce
|
|
4812
|
+
).toString();
|
|
4813
|
+
const hashMakerFirst = minaParticipantChannelHashField(
|
|
4814
|
+
Poseidon,
|
|
4815
|
+
PublicKey,
|
|
4816
|
+
inputs.swapSignerAddress,
|
|
4817
|
+
inputs.recipient,
|
|
4818
|
+
channelNonce
|
|
4819
|
+
).toString();
|
|
4820
|
+
let participantA;
|
|
4821
|
+
let participantB;
|
|
4822
|
+
let recipientRole;
|
|
4823
|
+
if (hashRecipientFirst === inputs.onChainChannelHash) {
|
|
4824
|
+
participantA = inputs.recipient;
|
|
4825
|
+
participantB = inputs.swapSignerAddress;
|
|
4826
|
+
recipientRole = "A";
|
|
4827
|
+
} else if (hashMakerFirst === inputs.onChainChannelHash) {
|
|
4828
|
+
participantA = inputs.swapSignerAddress;
|
|
4829
|
+
participantB = inputs.recipient;
|
|
4830
|
+
recipientRole = "B";
|
|
4831
|
+
} else {
|
|
4832
|
+
throw new MinaSettlementError(
|
|
4833
|
+
"CHANNEL_HASH_MISMATCH",
|
|
4834
|
+
`neither ordering of recipient ${inputs.recipient} / maker ${inputs.swapSignerAddress} reproduces the on-chain channelHash ${inputs.onChainChannelHash} (channelNonce ${channelNonce})`
|
|
4835
|
+
);
|
|
4836
|
+
}
|
|
4837
|
+
const recipientBalance = inputs.cumulativeAmount;
|
|
4838
|
+
const makerBalance = inputs.depositTotal - inputs.cumulativeAmount;
|
|
4839
|
+
const balanceA = recipientRole === "A" ? recipientBalance : makerBalance;
|
|
4840
|
+
const balanceB = inputs.depositTotal - balanceA;
|
|
4841
|
+
const balanceCommitment = minaBalanceCommitment(
|
|
4842
|
+
Poseidon,
|
|
4843
|
+
balanceA,
|
|
4844
|
+
balanceB,
|
|
4845
|
+
salt
|
|
4846
|
+
).toString();
|
|
4847
|
+
const recipientPrivateKeyBase58 = hexToMinaBase58PrivateKey4(
|
|
4848
|
+
inputs.recipientPrivateKey
|
|
4849
|
+
);
|
|
4850
|
+
const built = await buildMinaPaymentChannelProof({
|
|
4851
|
+
zkAppAddress: inputs.channelId,
|
|
4852
|
+
minaPrivateKeyBase58: recipientPrivateKeyBase58,
|
|
4853
|
+
signerPublicKey: inputs.recipient,
|
|
4854
|
+
balanceA,
|
|
4855
|
+
balanceB,
|
|
4856
|
+
salt,
|
|
4857
|
+
nonce: inputs.nonce,
|
|
4858
|
+
participantA,
|
|
4859
|
+
participantB,
|
|
4860
|
+
channelNonce,
|
|
4861
|
+
proofEncoding: "json"
|
|
4862
|
+
});
|
|
4863
|
+
if (built.balanceCommitment !== balanceCommitment) {
|
|
4864
|
+
throw new Error(
|
|
4865
|
+
`co-sign commitment drift: builder ${built.balanceCommitment} != ${balanceCommitment}`
|
|
4866
|
+
);
|
|
4867
|
+
}
|
|
4868
|
+
const recipientSignature = parseProofSignature(built.proof);
|
|
4869
|
+
const signatureA = recipientRole === "A" ? recipientSignature : inputs.makerSignature;
|
|
4870
|
+
const signatureB = recipientRole === "B" ? recipientSignature : inputs.makerSignature;
|
|
4871
|
+
return {
|
|
4872
|
+
channelId: inputs.channelId,
|
|
4873
|
+
balanceA,
|
|
4874
|
+
balanceB,
|
|
4875
|
+
salt,
|
|
4876
|
+
nonce: inputs.nonce,
|
|
4877
|
+
channelNonce,
|
|
4878
|
+
balanceCommitment,
|
|
4879
|
+
participantA,
|
|
4880
|
+
participantB,
|
|
4881
|
+
recipientRole,
|
|
4882
|
+
recipientSignature,
|
|
4883
|
+
...signatureA ? { signatureA } : {},
|
|
4884
|
+
...signatureB ? { signatureB } : {},
|
|
4885
|
+
makerSignatureMissing: inputs.makerSignature === void 0
|
|
4886
|
+
};
|
|
4887
|
+
}
|
|
4888
|
+
async function submitMinaSettlement(bundle, context) {
|
|
4889
|
+
if (bundle.chainKind !== "mina") {
|
|
4890
|
+
throw new MinaSettlementError(
|
|
4891
|
+
"NOT_MINA_BUNDLE",
|
|
4892
|
+
`submitMinaSettlement only settles mina bundles (got ${bundle.chainKind} for ${bundle.chain})`
|
|
4893
|
+
);
|
|
4894
|
+
}
|
|
4895
|
+
if (!context.graphqlUrl) {
|
|
4896
|
+
throw new MinaSettlementError(
|
|
4897
|
+
"NO_GRAPHQL_CONFIGURED",
|
|
4898
|
+
`no Mina graphqlUrl configured for "${bundle.chain}" \u2014 set minaChannel.graphqlUrl to enable receive-side settlement.`
|
|
4899
|
+
);
|
|
4900
|
+
}
|
|
4901
|
+
const graphqlUrl = context.graphqlUrl;
|
|
4902
|
+
const channelNonce = context.channelNonce ?? 0n;
|
|
4903
|
+
const nonce = BigInt(bundle.nonce);
|
|
4904
|
+
const cumulativeAmount = BigInt(bundle.cumulativeAmount);
|
|
4905
|
+
const read = context.reader ?? readMinaChannelState;
|
|
4906
|
+
const state = await read(graphqlUrl, bundle.channelId);
|
|
4907
|
+
if (state.channelState !== MINA_CHANNEL_STATE.OPEN) {
|
|
4908
|
+
throw new MinaSettlementError(
|
|
4909
|
+
"CHANNEL_NOT_OPEN",
|
|
4910
|
+
`channel ${bundle.channelId} is not OPEN (channelState=${state.channelState}); claimFromChannel only applies to an OPEN channel.`
|
|
4911
|
+
);
|
|
4912
|
+
}
|
|
4913
|
+
if (nonce <= state.nonceField) {
|
|
4914
|
+
throw new MinaSettlementError(
|
|
4915
|
+
"NONCE_NOT_ADVANCING",
|
|
4916
|
+
`claim nonce ${nonce} does not advance the on-chain nonceField ${state.nonceField} for ${bundle.channelId} (already claimed).`
|
|
4917
|
+
);
|
|
4918
|
+
}
|
|
4919
|
+
const claim = await buildMinaCoSignedClaim({
|
|
4920
|
+
channelId: bundle.channelId,
|
|
4921
|
+
nonce,
|
|
4922
|
+
cumulativeAmount,
|
|
4923
|
+
recipient: bundle.recipient,
|
|
4924
|
+
swapSignerAddress: bundle.swapSignerAddress,
|
|
4925
|
+
depositTotal: state.depositTotal,
|
|
4926
|
+
onChainChannelHash: state.channelHash,
|
|
4927
|
+
recipientPrivateKey: context.recipientPrivateKey,
|
|
4928
|
+
channelNonce,
|
|
4929
|
+
...context.makerSignature ? { makerSignature: context.makerSignature } : {}
|
|
4930
|
+
});
|
|
4931
|
+
if (claim.makerSignatureMissing || !claim.signatureA || !claim.signatureB) {
|
|
4932
|
+
throw new MinaSettlementError(
|
|
4933
|
+
"MINA_MAKER_COSIGN_REQUIRED",
|
|
4934
|
+
`on-chain claimFromChannel is dual-party: it needs the maker's payment-channel-commitment signature over [commitment, nonce, channelHash] in addition to the recipient's co-signature. The swap-wire claim only carries the maker's balanceProofFieldsMina signature (a different message), so the maker must additionally deliver an on-chain-form co-signature. Recipient co-signature assembled and ready (${bundle.channelId} nonce ${nonce}).`
|
|
4935
|
+
);
|
|
4936
|
+
}
|
|
4937
|
+
const submitter = context.submitter ?? createO1jsMinaClaimSubmitter();
|
|
4938
|
+
const { txHash } = await submitter.claimFromChannel({
|
|
4939
|
+
graphqlUrl,
|
|
4940
|
+
channelId: bundle.channelId,
|
|
4941
|
+
balanceA: claim.balanceA,
|
|
4942
|
+
balanceB: claim.balanceB,
|
|
4943
|
+
salt: claim.salt,
|
|
4944
|
+
nonce: claim.nonce,
|
|
4945
|
+
participantA: claim.participantA,
|
|
4946
|
+
participantB: claim.participantB,
|
|
4947
|
+
channelNonce: claim.channelNonce,
|
|
4948
|
+
signatureA: claim.signatureA,
|
|
4949
|
+
signatureB: claim.signatureB,
|
|
4950
|
+
feePayerPrivateKey: context.feePayerPrivateKey ?? context.recipientPrivateKey,
|
|
4951
|
+
...context.txFeeNanomina !== void 0 ? { txFeeNanomina: context.txFeeNanomina } : {}
|
|
4952
|
+
});
|
|
4953
|
+
return { txHash };
|
|
4954
|
+
}
|
|
4955
|
+
var DEFAULT_MINA_TX_FEE_NANOMINA = 100000000n;
|
|
4956
|
+
function createO1jsMinaClaimSubmitter() {
|
|
4957
|
+
return {
|
|
4958
|
+
async claimFromChannel(args) {
|
|
4959
|
+
try {
|
|
4960
|
+
const o1js = await import("o1js");
|
|
4961
|
+
const {
|
|
4962
|
+
Mina,
|
|
4963
|
+
PrivateKey,
|
|
4964
|
+
PublicKey,
|
|
4965
|
+
Field,
|
|
4966
|
+
Poseidon,
|
|
4967
|
+
Signature,
|
|
4968
|
+
fetchAccount
|
|
4969
|
+
} = o1js;
|
|
4970
|
+
const zkAppMod = await import("@toon-protocol/mina-zkapp");
|
|
4971
|
+
const PaymentChannel = zkAppMod.PaymentChannel;
|
|
4972
|
+
Mina.setActiveInstance(Mina.Network(args.graphqlUrl));
|
|
4973
|
+
const feePayerKey = PrivateKey.fromBase58(
|
|
4974
|
+
hexToMinaBase58PrivateKey4(args.feePayerPrivateKey)
|
|
4975
|
+
);
|
|
4976
|
+
const feePayerPub = feePayerKey.toPublicKey();
|
|
4977
|
+
await PaymentChannel.compile();
|
|
4978
|
+
const zkAppPub = PublicKey.fromBase58(args.channelId);
|
|
4979
|
+
await fetchAccount({ publicKey: zkAppPub });
|
|
4980
|
+
await fetchAccount({ publicKey: feePayerPub });
|
|
4981
|
+
const zkApp = new PaymentChannel(zkAppPub);
|
|
4982
|
+
const balA = Field(args.balanceA);
|
|
4983
|
+
const balB = Field(args.balanceB);
|
|
4984
|
+
const saltField = Field(args.salt);
|
|
4985
|
+
const newNonce = Field(args.nonce);
|
|
4986
|
+
const channelNonce = Field(args.channelNonce);
|
|
4987
|
+
const newBalanceCommitment = Poseidon.hash([balA, balB, saltField]);
|
|
4988
|
+
const sigA = Signature.fromJSON({
|
|
4989
|
+
r: args.signatureA.r,
|
|
4990
|
+
s: args.signatureA.s
|
|
4991
|
+
});
|
|
4992
|
+
const sigB = Signature.fromJSON({
|
|
4993
|
+
r: args.signatureB.r,
|
|
4994
|
+
s: args.signatureB.s
|
|
4995
|
+
});
|
|
4996
|
+
const partA = PublicKey.fromBase58(args.participantA);
|
|
4997
|
+
const partB = PublicKey.fromBase58(args.participantB);
|
|
4998
|
+
const fee = (args.txFeeNanomina ?? DEFAULT_MINA_TX_FEE_NANOMINA).toString();
|
|
4999
|
+
const txn = await Mina.transaction(
|
|
5000
|
+
{ sender: feePayerPub, fee },
|
|
5001
|
+
async () => {
|
|
5002
|
+
await zkApp.claimFromChannel(
|
|
5003
|
+
balA,
|
|
5004
|
+
balB,
|
|
5005
|
+
saltField,
|
|
5006
|
+
sigA,
|
|
5007
|
+
sigB,
|
|
5008
|
+
partA,
|
|
5009
|
+
partB,
|
|
5010
|
+
channelNonce,
|
|
5011
|
+
newBalanceCommitment,
|
|
5012
|
+
newNonce
|
|
5013
|
+
);
|
|
5014
|
+
}
|
|
5015
|
+
);
|
|
5016
|
+
await txn.prove();
|
|
5017
|
+
const sent = await txn.sign([feePayerKey]).send();
|
|
5018
|
+
return { txHash: sent.hash ?? "" };
|
|
5019
|
+
} catch (err) {
|
|
5020
|
+
throw new MinaSettlementError(
|
|
5021
|
+
"PROVING_FAILED",
|
|
5022
|
+
err instanceof Error ? err.message : String(err)
|
|
5023
|
+
);
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
};
|
|
5027
|
+
}
|
|
5028
|
+
|
|
4734
5029
|
// src/ToonClient.ts
|
|
5030
|
+
function parseMakerMinaSignature(raw) {
|
|
5031
|
+
if (raw && typeof raw.r === "string" && raw.r.length > 0 && typeof raw.s === "string" && raw.s.length > 0) {
|
|
5032
|
+
return { r: raw.r, s: raw.s };
|
|
5033
|
+
}
|
|
5034
|
+
return void 0;
|
|
5035
|
+
}
|
|
4735
5036
|
var ToonClient = class {
|
|
4736
5037
|
config;
|
|
4737
5038
|
state = null;
|
|
@@ -5016,34 +5317,11 @@ var ToonClient = class {
|
|
|
5016
5317
|
const writeData = buildStoreWriteEnvelope(event, options?.proxyPath);
|
|
5017
5318
|
const destination = options?.destination ?? this.config.destinationAddress;
|
|
5018
5319
|
const transport = this.getClaimTransport();
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
const negotiation = this.peerNegotiations.get(peerId);
|
|
5025
|
-
if (!negotiation) {
|
|
5026
|
-
throw new ToonClientError(
|
|
5027
|
-
`No negotiation metadata for peer "${peerId}" \u2014 was bootstrap completed?`,
|
|
5028
|
-
"PEER_NOT_NEGOTIATED"
|
|
5029
|
-
);
|
|
5030
|
-
}
|
|
5031
|
-
const channelId = await this.channelManager.ensureChannel(
|
|
5032
|
-
peerId,
|
|
5033
|
-
negotiation
|
|
5034
|
-
);
|
|
5035
|
-
const proof = await this.channelManager.signBalanceProof(
|
|
5036
|
-
channelId,
|
|
5037
|
-
BigInt(amount)
|
|
5038
|
-
);
|
|
5039
|
-
const signer = this.channelManager.getSignerForChannel(channelId);
|
|
5040
|
-
claimMessage = signer.buildClaimMessage(proof, this.getPublicKey());
|
|
5041
|
-
} else {
|
|
5042
|
-
throw new ToonClientError(
|
|
5043
|
-
"No claim provided and no channel manager configured",
|
|
5044
|
-
"MISSING_CLAIM"
|
|
5045
|
-
);
|
|
5046
|
-
}
|
|
5320
|
+
const claimMessage = await this.resolveClaimForDestination(
|
|
5321
|
+
destination,
|
|
5322
|
+
BigInt(amount),
|
|
5323
|
+
options?.claim
|
|
5324
|
+
);
|
|
5047
5325
|
const response = await transport.sendIlpPacketWithClaim(
|
|
5048
5326
|
{
|
|
5049
5327
|
destination,
|
|
@@ -5250,8 +5528,6 @@ var ToonClient = class {
|
|
|
5250
5528
|
}
|
|
5251
5529
|
/**
|
|
5252
5530
|
* Shared claim-resolution logic used by `publishEvent` and `sendSwapPacket`.
|
|
5253
|
-
* TODO(12.5 followup): also factor `publishEvent`'s inline claim resolution
|
|
5254
|
-
* to call this helper. Kept duplicated for now to minimize regression risk.
|
|
5255
5531
|
*/
|
|
5256
5532
|
async resolveClaimForDestination(destination, amount, explicitClaim) {
|
|
5257
5533
|
if (explicitClaim) {
|
|
@@ -5460,6 +5736,22 @@ var ToonClient = class {
|
|
|
5460
5736
|
* swap/settle-received-claims.ts module doc).
|
|
5461
5737
|
*/
|
|
5462
5738
|
async settleSwapBundle(bundle) {
|
|
5739
|
+
if (bundle.chainKind === "mina") {
|
|
5740
|
+
if (!this.minaPrivateKey) {
|
|
5741
|
+
throw new Error(
|
|
5742
|
+
"Mina signer not configured (no mnemonic / mina-signer) \u2014 cannot co-sign the receive-side claim."
|
|
5743
|
+
);
|
|
5744
|
+
}
|
|
5745
|
+
const makerSignature = parseMakerMinaSignature(
|
|
5746
|
+
this.config.swapMinaMakerSignatures?.[bundle.channelId]
|
|
5747
|
+
);
|
|
5748
|
+
const { txHash } = await submitMinaSettlement(bundle, {
|
|
5749
|
+
recipientPrivateKey: this.minaPrivateKey,
|
|
5750
|
+
...this.config.minaChannel?.graphqlUrl ? { graphqlUrl: this.config.minaChannel.graphqlUrl } : {},
|
|
5751
|
+
...makerSignature ? { makerSignature } : {}
|
|
5752
|
+
});
|
|
5753
|
+
return { txHash };
|
|
5754
|
+
}
|
|
5463
5755
|
if (bundle.chainKind !== "evm") {
|
|
5464
5756
|
throw new Error(
|
|
5465
5757
|
`Swap settlement submission for ${bundle.chainKind} (${bundle.chain}) is not wired yet \u2014 EVM only today.`
|
|
@@ -6309,6 +6601,96 @@ function ingestReceivedClaims(params) {
|
|
|
6309
6601
|
return { verified, rejected, legacy, valueReceived };
|
|
6310
6602
|
}
|
|
6311
6603
|
|
|
6604
|
+
// src/swap/preimage-retention.ts
|
|
6605
|
+
function copy(entry) {
|
|
6606
|
+
return {
|
|
6607
|
+
packetIndex: entry.packetIndex,
|
|
6608
|
+
preimage: Uint8Array.from(entry.preimage),
|
|
6609
|
+
condition: Uint8Array.from(entry.condition),
|
|
6610
|
+
retainedAt: entry.retainedAt
|
|
6611
|
+
};
|
|
6612
|
+
}
|
|
6613
|
+
var InMemoryPreimageRetentionStore = class {
|
|
6614
|
+
entries = /* @__PURE__ */ new Map();
|
|
6615
|
+
retain(entry) {
|
|
6616
|
+
this.entries.set(entry.packetIndex, copy(entry));
|
|
6617
|
+
}
|
|
6618
|
+
get(packetIndex) {
|
|
6619
|
+
const entry = this.entries.get(packetIndex);
|
|
6620
|
+
return entry ? copy(entry) : void 0;
|
|
6621
|
+
}
|
|
6622
|
+
take(packetIndex) {
|
|
6623
|
+
const entry = this.entries.get(packetIndex);
|
|
6624
|
+
if (!entry) return void 0;
|
|
6625
|
+
this.entries.delete(packetIndex);
|
|
6626
|
+
return copy(entry);
|
|
6627
|
+
}
|
|
6628
|
+
size() {
|
|
6629
|
+
return this.entries.size;
|
|
6630
|
+
}
|
|
6631
|
+
clear() {
|
|
6632
|
+
this.entries.clear();
|
|
6633
|
+
}
|
|
6634
|
+
};
|
|
6635
|
+
|
|
6636
|
+
// src/swap/atomic-reveal.ts
|
|
6637
|
+
function rollbackWatermark(store, chain, channelId, prior) {
|
|
6638
|
+
if (prior === void 0) {
|
|
6639
|
+
store.delete(chain, channelId);
|
|
6640
|
+
} else {
|
|
6641
|
+
store.save(prior);
|
|
6642
|
+
}
|
|
6643
|
+
}
|
|
6644
|
+
async function ingestAndReveal(params) {
|
|
6645
|
+
const { reveal, preimages, claims, store, ...shared } = params;
|
|
6646
|
+
const revealed = [];
|
|
6647
|
+
const rolledBack = [];
|
|
6648
|
+
const rejected = [];
|
|
6649
|
+
const legacy = [];
|
|
6650
|
+
let valueRevealed = 0n;
|
|
6651
|
+
for (const claim of claims) {
|
|
6652
|
+
const hasMeta = hasSettlementMetadata(claim);
|
|
6653
|
+
const chain = hasMeta ? claim.pair.to.chain : void 0;
|
|
6654
|
+
const channelId = hasMeta ? claim.channelId : void 0;
|
|
6655
|
+
const prior = chain !== void 0 && channelId !== void 0 ? store.load(chain, channelId) : void 0;
|
|
6656
|
+
const ingest = ingestReceivedClaims({ ...shared, claims: [claim], store });
|
|
6657
|
+
if (ingest.legacy.length > 0) {
|
|
6658
|
+
legacy.push(claim);
|
|
6659
|
+
continue;
|
|
6660
|
+
}
|
|
6661
|
+
const rejection = ingest.rejected[0];
|
|
6662
|
+
if (rejection) {
|
|
6663
|
+
rejected.push(rejection);
|
|
6664
|
+
continue;
|
|
6665
|
+
}
|
|
6666
|
+
const verified = ingest.verified[0];
|
|
6667
|
+
if (!verified || chain === void 0 || channelId === void 0) continue;
|
|
6668
|
+
const advance = verified.watermarkAdvance;
|
|
6669
|
+
const preimage = preimages?.take(claim.packetIndex);
|
|
6670
|
+
let outcome;
|
|
6671
|
+
try {
|
|
6672
|
+
outcome = await reveal(claim, preimage);
|
|
6673
|
+
} catch (err) {
|
|
6674
|
+
outcome = {
|
|
6675
|
+
decision: "withheld",
|
|
6676
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
6677
|
+
};
|
|
6678
|
+
}
|
|
6679
|
+
if (outcome.decision === "revealed") {
|
|
6680
|
+
revealed.push({ claim, watermarkAdvance: advance });
|
|
6681
|
+
valueRevealed += advance;
|
|
6682
|
+
continue;
|
|
6683
|
+
}
|
|
6684
|
+
rollbackWatermark(store, chain, channelId, prior);
|
|
6685
|
+
rolledBack.push({
|
|
6686
|
+
claim,
|
|
6687
|
+
watermarkAdvance: advance,
|
|
6688
|
+
reason: outcome.reason ?? "reveal withheld"
|
|
6689
|
+
});
|
|
6690
|
+
}
|
|
6691
|
+
return { revealed, rolledBack, rejected, legacy, valueRevealed };
|
|
6692
|
+
}
|
|
6693
|
+
|
|
6312
6694
|
// src/faucet.ts
|
|
6313
6695
|
function defaultFaucetTimeout(chain) {
|
|
6314
6696
|
return chain === "mina" ? 12e4 : 3e4;
|
|
@@ -7432,12 +7814,15 @@ export {
|
|
|
7432
7814
|
ILP_CLAIM_HEADER,
|
|
7433
7815
|
ILP_CLAIM_WRAPPED_HEADER,
|
|
7434
7816
|
ILP_PEER_ID_HEADER,
|
|
7817
|
+
InMemoryPreimageRetentionStore,
|
|
7435
7818
|
InMemoryReceivedClaimStore,
|
|
7436
7819
|
JsonFileReceivedClaimStore,
|
|
7437
7820
|
KeyManager,
|
|
7438
7821
|
KindRegistry,
|
|
7439
7822
|
MIME_A2UI,
|
|
7440
7823
|
MIME_MCP_APP,
|
|
7824
|
+
MINA_CHANNEL_STATE,
|
|
7825
|
+
MinaSettlementError,
|
|
7441
7826
|
MinaSigner,
|
|
7442
7827
|
NetworkError,
|
|
7443
7828
|
OnChainChannelClient,
|
|
@@ -7454,12 +7839,14 @@ export {
|
|
|
7454
7839
|
buildBackupEvent,
|
|
7455
7840
|
buildBackupFilter,
|
|
7456
7841
|
buildConsentRequest,
|
|
7842
|
+
buildMinaCoSignedClaim,
|
|
7457
7843
|
buildRendererEventTemplate,
|
|
7458
7844
|
buildSettlementInfo,
|
|
7459
7845
|
buildStoreWriteEnvelope,
|
|
7460
7846
|
buildSwapSettlements,
|
|
7461
7847
|
buildUiCoordinate,
|
|
7462
7848
|
classifyIntent,
|
|
7849
|
+
createO1jsMinaClaimSubmitter,
|
|
7463
7850
|
decodeEvmSettlementTx,
|
|
7464
7851
|
decryptMnemonic2 as decryptMnemonic,
|
|
7465
7852
|
defaultFaucetTimeout,
|
|
@@ -7482,6 +7869,7 @@ export {
|
|
|
7482
7869
|
hasSettlementMetadata,
|
|
7483
7870
|
httpEndpointToBtpUrl,
|
|
7484
7871
|
importKeystore,
|
|
7872
|
+
ingestAndReveal,
|
|
7485
7873
|
ingestReceivedClaims,
|
|
7486
7874
|
isInsufficientGasError,
|
|
7487
7875
|
isPrfSupported,
|
|
@@ -7503,6 +7891,7 @@ export {
|
|
|
7503
7891
|
readEvmNativeBalance,
|
|
7504
7892
|
readEvmTokenBalance,
|
|
7505
7893
|
readMinaBalance,
|
|
7894
|
+
readMinaChannelState,
|
|
7506
7895
|
readMinaDepositTotal,
|
|
7507
7896
|
readSolanaNativeBalance,
|
|
7508
7897
|
readSolanaTokenBalance,
|
|
@@ -7517,6 +7906,7 @@ export {
|
|
|
7517
7906
|
selectLatestAddressable,
|
|
7518
7907
|
serializeHttpRequest,
|
|
7519
7908
|
submitEvmSettlement,
|
|
7909
|
+
submitMinaSettlement,
|
|
7520
7910
|
validateConfig,
|
|
7521
7911
|
validateMnemonic,
|
|
7522
7912
|
verifyRendererTrust,
|