@bronlabs/intents-sdk 1.0.133 → 1.0.135
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/abi/Metadata.json +34 -0
- package/abi/OrderEngine.json +118 -0
- package/dist/attestation.d.ts +54 -0
- package/dist/attestation.js +132 -0
- package/dist/attestation.js.map +1 -0
- package/dist/contracts.d.ts +8 -0
- package/dist/contracts.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/networks/btc.d.ts +7 -1
- package/dist/networks/btc.js +44 -11
- package/dist/networks/btc.js.map +1 -1
- package/dist/networks/canton.d.ts +7 -1
- package/dist/networks/canton.js +33 -0
- package/dist/networks/canton.js.map +1 -1
- package/dist/networks/cosmos.d.ts +7 -2
- package/dist/networks/cosmos.js +46 -17
- package/dist/networks/cosmos.js.map +1 -1
- package/dist/networks/evm.d.ts +5 -1
- package/dist/networks/evm.js +8 -1
- package/dist/networks/evm.js.map +1 -1
- package/dist/networks/sol.d.ts +5 -1
- package/dist/networks/sol.js +56 -14
- package/dist/networks/sol.js.map +1 -1
- package/dist/networks/ton.d.ts +6 -1
- package/dist/networks/ton.js +19 -4
- package/dist/networks/ton.js.map +1 -1
- package/dist/networks/trx.d.ts +5 -1
- package/dist/networks/trx.js +9 -5
- package/dist/networks/trx.js.map +1 -1
- package/dist/networks/xrp.d.ts +5 -1
- package/dist/networks/xrp.js +11 -0
- package/dist/networks/xrp.js.map +1 -1
- package/package.json +5 -2
package/abi/Metadata.json
CHANGED
|
@@ -358,6 +358,40 @@
|
|
|
358
358
|
"internalType": "uint128",
|
|
359
359
|
"name": "totalFeesPercent_e4",
|
|
360
360
|
"type": "uint128"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"components": [
|
|
364
|
+
{
|
|
365
|
+
"internalType": "bytes",
|
|
366
|
+
"name": "publicKey",
|
|
367
|
+
"type": "bytes"
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"internalType": "bytes",
|
|
371
|
+
"name": "signature",
|
|
372
|
+
"type": "bytes"
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
"internalType": "struct IOrderEngine.Attestation",
|
|
376
|
+
"name": "userTxAttestation",
|
|
377
|
+
"type": "tuple"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"components": [
|
|
381
|
+
{
|
|
382
|
+
"internalType": "bytes",
|
|
383
|
+
"name": "publicKey",
|
|
384
|
+
"type": "bytes"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"internalType": "bytes",
|
|
388
|
+
"name": "signature",
|
|
389
|
+
"type": "bytes"
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
"internalType": "struct IOrderEngine.Attestation",
|
|
393
|
+
"name": "solverTxAttestation",
|
|
394
|
+
"type": "tuple"
|
|
361
395
|
}
|
|
362
396
|
],
|
|
363
397
|
"internalType": "struct IMetadata.OrderFullResponse",
|
package/abi/OrderEngine.json
CHANGED
|
@@ -913,5 +913,123 @@
|
|
|
913
913
|
"outputs": [],
|
|
914
914
|
"stateMutability": "nonpayable",
|
|
915
915
|
"type": "function"
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
"inputs": [
|
|
919
|
+
{
|
|
920
|
+
"internalType": "string",
|
|
921
|
+
"name": "_orderId",
|
|
922
|
+
"type": "string"
|
|
923
|
+
}
|
|
924
|
+
],
|
|
925
|
+
"name": "getSolverTxAttestation",
|
|
926
|
+
"outputs": [
|
|
927
|
+
{
|
|
928
|
+
"components": [
|
|
929
|
+
{
|
|
930
|
+
"internalType": "bytes",
|
|
931
|
+
"name": "publicKey",
|
|
932
|
+
"type": "bytes"
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
"internalType": "bytes",
|
|
936
|
+
"name": "signature",
|
|
937
|
+
"type": "bytes"
|
|
938
|
+
}
|
|
939
|
+
],
|
|
940
|
+
"internalType": "struct IOrderEngine.Attestation",
|
|
941
|
+
"name": "",
|
|
942
|
+
"type": "tuple"
|
|
943
|
+
}
|
|
944
|
+
],
|
|
945
|
+
"stateMutability": "view",
|
|
946
|
+
"type": "function"
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
"inputs": [
|
|
950
|
+
{
|
|
951
|
+
"internalType": "string",
|
|
952
|
+
"name": "_orderId",
|
|
953
|
+
"type": "string"
|
|
954
|
+
}
|
|
955
|
+
],
|
|
956
|
+
"name": "getUserTxAttestation",
|
|
957
|
+
"outputs": [
|
|
958
|
+
{
|
|
959
|
+
"components": [
|
|
960
|
+
{
|
|
961
|
+
"internalType": "bytes",
|
|
962
|
+
"name": "publicKey",
|
|
963
|
+
"type": "bytes"
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
"internalType": "bytes",
|
|
967
|
+
"name": "signature",
|
|
968
|
+
"type": "bytes"
|
|
969
|
+
}
|
|
970
|
+
],
|
|
971
|
+
"internalType": "struct IOrderEngine.Attestation",
|
|
972
|
+
"name": "",
|
|
973
|
+
"type": "tuple"
|
|
974
|
+
}
|
|
975
|
+
],
|
|
976
|
+
"stateMutability": "view",
|
|
977
|
+
"type": "function"
|
|
978
|
+
},
|
|
979
|
+
{
|
|
980
|
+
"inputs": [
|
|
981
|
+
{
|
|
982
|
+
"internalType": "string",
|
|
983
|
+
"name": "_orderId",
|
|
984
|
+
"type": "string"
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
"internalType": "string",
|
|
988
|
+
"name": "_solverTxHash",
|
|
989
|
+
"type": "string"
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
"internalType": "bytes",
|
|
993
|
+
"name": "_publicKey",
|
|
994
|
+
"type": "bytes"
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
"internalType": "bytes",
|
|
998
|
+
"name": "_signature",
|
|
999
|
+
"type": "bytes"
|
|
1000
|
+
}
|
|
1001
|
+
],
|
|
1002
|
+
"name": "setSolverTxOnQuoteNetworkWithAttestation",
|
|
1003
|
+
"outputs": [],
|
|
1004
|
+
"stateMutability": "nonpayable",
|
|
1005
|
+
"type": "function"
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
"inputs": [
|
|
1009
|
+
{
|
|
1010
|
+
"internalType": "string",
|
|
1011
|
+
"name": "_orderId",
|
|
1012
|
+
"type": "string"
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
"internalType": "string",
|
|
1016
|
+
"name": "_userTxHash",
|
|
1017
|
+
"type": "string"
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
"internalType": "bytes",
|
|
1021
|
+
"name": "_publicKey",
|
|
1022
|
+
"type": "bytes"
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
"internalType": "bytes",
|
|
1026
|
+
"name": "_signature",
|
|
1027
|
+
"type": "bytes"
|
|
1028
|
+
}
|
|
1029
|
+
],
|
|
1030
|
+
"name": "setUserTxOnBaseNetworkWithAttestation",
|
|
1031
|
+
"outputs": [],
|
|
1032
|
+
"stateMutability": "nonpayable",
|
|
1033
|
+
"type": "function"
|
|
916
1034
|
}
|
|
917
1035
|
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export declare const ATTESTATION_DOMAIN = "BRON_INTENT_SETTLEMENT_V1";
|
|
2
|
+
export type AttestationLeg = 'user' | 'solver';
|
|
3
|
+
export declare enum SignatureScheme {
|
|
4
|
+
Secp256k1 = "secp256k1",
|
|
5
|
+
Ed25519 = "ed25519"
|
|
6
|
+
}
|
|
7
|
+
export interface AttestationMessageParams {
|
|
8
|
+
orderEngine: string;
|
|
9
|
+
leg: AttestationLeg;
|
|
10
|
+
orderId: string;
|
|
11
|
+
counterparty: string;
|
|
12
|
+
token: string;
|
|
13
|
+
amount: bigint;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Canonical attestation preimage bytes. secp256k1 chains sign keccak256(preimage); ed25519 chains
|
|
17
|
+
* sign these raw bytes (RFC 8032 hashes internally).
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildAttestationPreimage(p: AttestationMessageParams): Uint8Array;
|
|
20
|
+
export declare function secp256k1Digest(preimage: Uint8Array): string;
|
|
21
|
+
/**
|
|
22
|
+
* Capability a Network gains to participate in payer-signature binding. Kept OFF the public
|
|
23
|
+
* `Network` interface (optional/internal) so external Network implementers don't break.
|
|
24
|
+
*/
|
|
25
|
+
export interface AttestationCapable {
|
|
26
|
+
readonly signatureScheme: SignatureScheme;
|
|
27
|
+
/** Derive the chain address that the public key controls (compared against the order's from). */
|
|
28
|
+
addressFromPublicKey(publicKey: string): Promise<string> | string;
|
|
29
|
+
/** Verify the signature is valid for `publicKey` over the canonical preimage. */
|
|
30
|
+
verifyAttestation(publicKey: string, signature: string, preimage: Uint8Array): Promise<boolean> | boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Optional sigBound override for networks where the settlement "from" is not the plain
|
|
33
|
+
* key-derived address (e.g. Canton party-ids carry a free-form hint next to the key fingerprint).
|
|
34
|
+
* When absent, sigBound is case-insensitive equality with `addressFromPublicKey`.
|
|
35
|
+
*/
|
|
36
|
+
matchesAddress?(publicKey: string, address: string): Promise<boolean> | boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare function isAttestationCapable<T>(network: T): network is T & AttestationCapable;
|
|
39
|
+
/** sigBound: does the public key control the order's settlement-from address? */
|
|
40
|
+
export declare function attestationKeyMatchesAddress(network: AttestationCapable, publicKey: string, address: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Recover the uncompressed public key from a secp256k1 signature over the preimage, or null if the
|
|
43
|
+
* signature is malformed / malleable. Rejects high-S (BIP-62 malleability). Accepts 64-byte (r||s)
|
|
44
|
+
* and 65-byte (r||s||v) signatures; for 64-byte sigs both recovery ids are tried — safe because the
|
|
45
|
+
* result is only accepted if it matches the submitted public key.
|
|
46
|
+
*/
|
|
47
|
+
export declare function recoverSecp256k1PublicKeys(preimage: Uint8Array, signature: string): string[];
|
|
48
|
+
export declare function verifySecp256k1(publicKey: string, signature: string, preimage: Uint8Array): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Strict RFC 8032 verification (zip215=false): canonical encoding, cofactor-correct, rejects
|
|
51
|
+
* low-order / non-canonical points. Enforces 32-byte public key and 64-byte signature. Async: uses
|
|
52
|
+
* verifyAsync (WebCrypto SHA-512) — the sync path requires a separately-configured sha512.
|
|
53
|
+
*/
|
|
54
|
+
export declare function verifyEd25519(publicKey: string, signature: string, preimage: Uint8Array): Promise<boolean>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import * as ed25519 from '@noble/ed25519';
|
|
3
|
+
// Payer-signature binding: the controller of a leg's settlement-from address signs this
|
|
4
|
+
// order-bound message with the key that controls that address. The oracle derives the signer's
|
|
5
|
+
// address from the public key, checks it equals the order's settlement-from address, and verifies
|
|
6
|
+
// the signature. Paired with the retained `tx.from == orderFrom` check this transitively proves
|
|
7
|
+
// `signer == tx.from`, i.e. the declared payer actually paid.
|
|
8
|
+
//
|
|
9
|
+
// The preimage binds everything known at signing time EXCEPT the tx hash (the attestation is signed
|
|
10
|
+
// in the same MPC request as the settlement tx, before the hash exists). Domain separation makes the
|
|
11
|
+
// digest structurally impossible to confuse with a real transaction hash or another protocol's
|
|
12
|
+
// payload — the settlement key also signs fund-moving txs, so a bare 32-byte signing primitive would
|
|
13
|
+
// be a signing oracle.
|
|
14
|
+
//
|
|
15
|
+
// CANONICAL ENCODING — both signer (Bron MPC / pilates) and verifier (oracle) MUST produce the exact
|
|
16
|
+
// same bytes. The preimage is the ABI encoding of the tuple below; the Scala MPC path must mirror it
|
|
17
|
+
// byte-for-byte (standard `abi.encode`). Do not reorder or change types without bumping the domain.
|
|
18
|
+
export const ATTESTATION_DOMAIN = 'BRON_INTENT_SETTLEMENT_V1';
|
|
19
|
+
export var SignatureScheme;
|
|
20
|
+
(function (SignatureScheme) {
|
|
21
|
+
SignatureScheme["Secp256k1"] = "secp256k1";
|
|
22
|
+
SignatureScheme["Ed25519"] = "ed25519";
|
|
23
|
+
})(SignatureScheme || (SignatureScheme = {}));
|
|
24
|
+
const ATTESTATION_TYPES = ['string', 'address', 'string', 'string', 'string', 'string', 'uint256'];
|
|
25
|
+
const EVM_ADDRESS_STRING = /^0x[0-9a-fA-F]{40}$/;
|
|
26
|
+
// counterparty/token are ABI 'string' (non-EVM legs carry base58/bech32/r-addresses), so their text
|
|
27
|
+
// is hashed verbatim — and the signer and the oracle source these fields independently. EVM-style
|
|
28
|
+
// 0x-addresses are re-checksummed to one canonical EIP-55 form so casing drift between the two sides
|
|
29
|
+
// can't false-reject a valid signature; non-EVM forms are case-sensitive and pass through untouched.
|
|
30
|
+
function canonicalAddressString(value) {
|
|
31
|
+
return EVM_ADDRESS_STRING.test(value) ? ethers.getAddress(value.toLowerCase()) : value;
|
|
32
|
+
}
|
|
33
|
+
const SECP256K1_N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
|
|
34
|
+
const SECP256K1_HALF_N = SECP256K1_N / 2n;
|
|
35
|
+
/**
|
|
36
|
+
* Canonical attestation preimage bytes. secp256k1 chains sign keccak256(preimage); ed25519 chains
|
|
37
|
+
* sign these raw bytes (RFC 8032 hashes internally).
|
|
38
|
+
*/
|
|
39
|
+
export function buildAttestationPreimage(p) {
|
|
40
|
+
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(ATTESTATION_TYPES, [
|
|
41
|
+
ATTESTATION_DOMAIN,
|
|
42
|
+
ethers.getAddress(p.orderEngine),
|
|
43
|
+
p.leg,
|
|
44
|
+
p.orderId,
|
|
45
|
+
canonicalAddressString(p.counterparty),
|
|
46
|
+
canonicalAddressString(p.token),
|
|
47
|
+
p.amount,
|
|
48
|
+
]);
|
|
49
|
+
return ethers.getBytes(encoded);
|
|
50
|
+
}
|
|
51
|
+
export function secp256k1Digest(preimage) {
|
|
52
|
+
return ethers.keccak256(preimage);
|
|
53
|
+
}
|
|
54
|
+
export function isAttestationCapable(network) {
|
|
55
|
+
const n = network;
|
|
56
|
+
return typeof n?.addressFromPublicKey === 'function' && typeof n?.verifyAttestation === 'function';
|
|
57
|
+
}
|
|
58
|
+
/** sigBound: does the public key control the order's settlement-from address? */
|
|
59
|
+
export async function attestationKeyMatchesAddress(network, publicKey, address) {
|
|
60
|
+
if (network.matchesAddress) {
|
|
61
|
+
return network.matchesAddress(publicKey, address);
|
|
62
|
+
}
|
|
63
|
+
const derived = await network.addressFromPublicKey(publicKey);
|
|
64
|
+
return derived.toLowerCase() === address.toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// secp256k1 (ECDSA) — EVM / Tron / XRP / Cosmos / BTC
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
/**
|
|
70
|
+
* Recover the uncompressed public key from a secp256k1 signature over the preimage, or null if the
|
|
71
|
+
* signature is malformed / malleable. Rejects high-S (BIP-62 malleability). Accepts 64-byte (r||s)
|
|
72
|
+
* and 65-byte (r||s||v) signatures; for 64-byte sigs both recovery ids are tried — safe because the
|
|
73
|
+
* result is only accepted if it matches the submitted public key.
|
|
74
|
+
*/
|
|
75
|
+
export function recoverSecp256k1PublicKeys(preimage, signature) {
|
|
76
|
+
const sig = ethers.getBytes(signature);
|
|
77
|
+
if (sig.length !== 64 && sig.length !== 65) {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const r = ethers.hexlify(sig.slice(0, 32));
|
|
81
|
+
const sBytes = sig.slice(32, 64);
|
|
82
|
+
const s = BigInt(ethers.hexlify(sBytes));
|
|
83
|
+
if (s === 0n || s > SECP256K1_HALF_N) {
|
|
84
|
+
return []; // reject zero and malleable high-S
|
|
85
|
+
}
|
|
86
|
+
const digest = secp256k1Digest(preimage);
|
|
87
|
+
const parities = sig.length === 65 ? [((sig[64] >= 27 ? sig[64] - 27 : sig[64]) & 1)] : [0, 1];
|
|
88
|
+
const keys = [];
|
|
89
|
+
for (const yParity of parities) {
|
|
90
|
+
try {
|
|
91
|
+
const recovered = ethers.SigningKey.recoverPublicKey(digest, ethers.Signature.from({ r, s: ethers.hexlify(sBytes), yParity }));
|
|
92
|
+
keys.push(ethers.SigningKey.computePublicKey(recovered, false).toLowerCase());
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// skip invalid recovery
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return keys;
|
|
99
|
+
}
|
|
100
|
+
export function verifySecp256k1(publicKey, signature, preimage) {
|
|
101
|
+
let target;
|
|
102
|
+
try {
|
|
103
|
+
target = ethers.SigningKey.computePublicKey(publicKey, false).toLowerCase();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return recoverSecp256k1PublicKeys(preimage, signature).includes(target);
|
|
109
|
+
}
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// ed25519 (EdDSA) — Solana / TON / Canton
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
/**
|
|
114
|
+
* Strict RFC 8032 verification (zip215=false): canonical encoding, cofactor-correct, rejects
|
|
115
|
+
* low-order / non-canonical points. Enforces 32-byte public key and 64-byte signature. Async: uses
|
|
116
|
+
* verifyAsync (WebCrypto SHA-512) — the sync path requires a separately-configured sha512.
|
|
117
|
+
*/
|
|
118
|
+
export async function verifyEd25519(publicKey, signature, preimage) {
|
|
119
|
+
const pub = ethers.getBytes(publicKey);
|
|
120
|
+
const sig = ethers.getBytes(signature);
|
|
121
|
+
if (pub.length !== 32 || sig.length !== 64) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
ed25519.Point.fromBytes(pub, false); // reject off-curve / non-canonical public key
|
|
126
|
+
return await ed25519.verifyAsync(sig, preimage, pub, { zip215: false });
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=attestation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"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"}
|
package/dist/contracts.d.ts
CHANGED
|
@@ -46,6 +46,10 @@ export interface SettlementFromAddresses {
|
|
|
46
46
|
userSettlementFromAddress: string;
|
|
47
47
|
solverSettlementFromAddress: string;
|
|
48
48
|
}
|
|
49
|
+
export interface Attestation {
|
|
50
|
+
publicKey: string;
|
|
51
|
+
signature: string;
|
|
52
|
+
}
|
|
49
53
|
interface NetworkParams {
|
|
50
54
|
gasLimit: number;
|
|
51
55
|
}
|
|
@@ -66,9 +70,13 @@ export interface OrderEngineContract {
|
|
|
66
70
|
}, networkParams?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
67
71
|
getOrder(orderId: string): Promise<Order>;
|
|
68
72
|
getSettlementFromAddresses(orderId: string): Promise<SettlementFromAddresses>;
|
|
73
|
+
getUserTxAttestation(orderId: string): Promise<Attestation>;
|
|
74
|
+
getSolverTxAttestation(orderId: string): Promise<Attestation>;
|
|
69
75
|
solverReact(orderId: string, solverAddressOnBaseChain: string, solverSettlementFromAddress: string, price: bigint, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
70
76
|
setUserTxOnBaseNetwork(orderId: string, txHash: string, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
77
|
+
setUserTxOnBaseNetworkWithAttestation(orderId: string, txHash: string, publicKey: ethers.BytesLike, signature: ethers.BytesLike, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
71
78
|
setSolverTxOnQuoteNetwork(orderId: string, txHash: string, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
79
|
+
setSolverTxOnQuoteNetworkWithAttestation(orderId: string, txHash: string, publicKey: ethers.BytesLike, signature: ethers.BytesLike, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
72
80
|
setOracleConfirmUserTx(orderId: string, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
73
81
|
setOracleConfirmSolverTx(orderId: string, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
|
74
82
|
executeUserTimeout(orderId: string, params?: NetworkParams): Promise<ethers.ContractTransactionResponse>;
|
package/dist/contracts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE/D,MAAM,CAAN,IAAY,WAWX;AAXD,WAAY,WAAW;IACrB,uDAAS,CAAA;IACT,iEAAc,CAAA;IACd,2EAAmB,CAAA;IACnB,qEAAgB,CAAA;IAChB,mGAA+B,CAAA;IAC/B,yEAAkB,CAAA;IAClB,uGAAiC,CAAA;IACjC,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,uDAAS,CAAA;AACX,CAAC,EAXW,WAAW,KAAX,WAAW,QAWtB;
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,3 +7,5 @@ export * from './contracts.js';
|
|
|
7
7
|
export * from './utils.js';
|
|
8
8
|
export { configureProxy, getProxyAgent, proxyFetch } from './proxy.js';
|
|
9
9
|
export { initNetworks } from './networks/index.js';
|
|
10
|
+
export type { Network, TransactionData } from './networks/index.js';
|
|
11
|
+
export * from './attestation.js';
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './contracts.js';
|
|
|
7
7
|
export * from './utils.js';
|
|
8
8
|
export { configureProxy, getProxyAgent, proxyFetch } from './proxy.js';
|
|
9
9
|
export { initNetworks } from './networks/index.js';
|
|
10
|
+
export * from './attestation.js';
|
|
10
11
|
// Monkey-patch BigInt.prototype.toJSON
|
|
11
12
|
BigInt.prototype.toJSON = function () {
|
|
12
13
|
return this.toString();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,uCAAuC;AACtC,MAAM,CAAC,SAAiB,CAAC,MAAM,GAAG;IACjC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,cAAc,kBAAkB,CAAC;AAEjC,uCAAuC;AACtC,MAAM,CAAC,SAAiB,CAAC,MAAM,GAAG;IACjC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC,CAAC"}
|
package/dist/networks/btc.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { Network, TransactionData } from './index.js';
|
|
2
|
-
|
|
2
|
+
import { AttestationCapable, SignatureScheme } from '../attestation.js';
|
|
3
|
+
export declare class BtcNetwork implements Network, AttestationCapable {
|
|
3
4
|
private readonly rpcUrl;
|
|
4
5
|
private readonly confirmations;
|
|
5
6
|
private readonly nativeAssetDecimals;
|
|
6
7
|
readonly retryDelay: number;
|
|
8
|
+
readonly signatureScheme = SignatureScheme.Secp256k1;
|
|
7
9
|
constructor(rpcUrl: string, confirmations?: number);
|
|
10
|
+
addressFromPublicKey(publicKey: string): string;
|
|
11
|
+
verifyAttestation(publicKey: string, signature: string, preimage: Uint8Array): boolean;
|
|
12
|
+
matchesAddress(publicKey: string, address: string): boolean;
|
|
13
|
+
private compressedPubkey;
|
|
8
14
|
ping(): Promise<void>;
|
|
9
15
|
getDecimals(tokenAddress: string): Promise<number>;
|
|
10
16
|
getTxData(txHash: string, tokenAddress: string, recipientAddress: string): Promise<TransactionData | undefined>;
|
package/dist/networks/btc.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as bitcoin from 'bitcoinjs-lib';
|
|
2
2
|
import { ECPairFactory } from 'ecpair';
|
|
3
3
|
import * as ecc from 'tiny-secp256k1';
|
|
4
|
+
import { ethers } from 'ethers';
|
|
5
|
+
import { SignatureScheme, verifySecp256k1 } from '../attestation.js';
|
|
4
6
|
import { log } from '../utils.js';
|
|
5
7
|
import { proxyFetch } from '../proxy.js';
|
|
6
8
|
import { randomUUID } from 'node:crypto';
|
|
@@ -9,9 +11,33 @@ export class BtcNetwork {
|
|
|
9
11
|
constructor(rpcUrl, confirmations = 6) {
|
|
10
12
|
this.nativeAssetDecimals = 8;
|
|
11
13
|
this.retryDelay = 30000;
|
|
14
|
+
this.signatureScheme = SignatureScheme.Secp256k1;
|
|
12
15
|
this.rpcUrl = rpcUrl;
|
|
13
16
|
this.confirmations = confirmations;
|
|
14
17
|
}
|
|
18
|
+
// Canonical (display) address is P2WPKH; sigBound matching is broader — see matchesAddress.
|
|
19
|
+
addressFromPublicKey(publicKey) {
|
|
20
|
+
return bitcoin.payments.p2wpkh({ pubkey: this.compressedPubkey(publicKey), network: bitcoin.networks.bitcoin }).address;
|
|
21
|
+
}
|
|
22
|
+
verifyAttestation(publicKey, signature, preimage) {
|
|
23
|
+
return verifySecp256k1(publicKey, signature, preimage);
|
|
24
|
+
}
|
|
25
|
+
// One secp256k1 key controls several single-sig address formats; orderFrom may be any of them, so
|
|
26
|
+
// sigBound accepts P2WPKH / P2SH-P2WPKH / P2PKH rather than only the canonical P2WPKH. Taproot
|
|
27
|
+
// (P2TR) is excluded — it signs with Schnorr, which this ECDSA verifyAttestation can't check.
|
|
28
|
+
matchesAddress(publicKey, address) {
|
|
29
|
+
const pubkey = this.compressedPubkey(publicKey);
|
|
30
|
+
const net = bitcoin.networks.bitcoin;
|
|
31
|
+
const candidates = [
|
|
32
|
+
bitcoin.payments.p2wpkh({ pubkey, network: net }).address,
|
|
33
|
+
bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2wpkh({ pubkey, network: net }), network: net }).address,
|
|
34
|
+
bitcoin.payments.p2pkh({ pubkey, network: net }).address,
|
|
35
|
+
];
|
|
36
|
+
return candidates.includes(address);
|
|
37
|
+
}
|
|
38
|
+
compressedPubkey(publicKey) {
|
|
39
|
+
return Buffer.from(ethers.getBytes(ethers.SigningKey.computePublicKey(publicKey, true)));
|
|
40
|
+
}
|
|
15
41
|
async ping() {
|
|
16
42
|
await this.rpcCall('getblockcount');
|
|
17
43
|
}
|
|
@@ -29,20 +55,27 @@ export class BtcNetwork {
|
|
|
29
55
|
const tx = await this.rpcCall('getrawtransaction', [txHash, true]);
|
|
30
56
|
if (!tx)
|
|
31
57
|
return;
|
|
32
|
-
//
|
|
58
|
+
// UTXO has no single canonical sender. Only attribute `from` for a single-input, non-coinbase
|
|
59
|
+
// tx; otherwise leave it empty so the oracle's senderValid fails closed. A multi-input tx can
|
|
60
|
+
// pool funds from addresses the attester doesn't control, which would break the senderValid →
|
|
61
|
+
// sigBound chain. An attested BTC settlement must therefore spend exactly one input.
|
|
33
62
|
let from = "";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
63
|
+
if (tx.vin.length === 1) {
|
|
64
|
+
const firstInput = tx.vin[0];
|
|
65
|
+
if (firstInput && firstInput.txid && firstInput.vout !== undefined) {
|
|
66
|
+
try {
|
|
67
|
+
const prevTx = await this.rpcCall('getrawtransaction', [firstInput.txid, true]);
|
|
68
|
+
const inputScript = prevTx.vout[firstInput.vout].scriptPubKey;
|
|
69
|
+
from = inputScript.address || inputScript.addresses?.[0] || "";
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
log.warn(`Failed to get sender address for ${txHash}: ${e}`);
|
|
73
|
+
}
|
|
43
74
|
}
|
|
44
75
|
}
|
|
45
|
-
|
|
76
|
+
else {
|
|
77
|
+
log.warn(`Transaction ${txHash} has ${tx.vin.length} inputs; refusing to attribute a single sender`);
|
|
78
|
+
}
|
|
46
79
|
const outputs = tx.vout.filter(vout => vout.scriptPubKey.address === recipientAddress || vout.scriptPubKey.addresses?.includes(recipientAddress));
|
|
47
80
|
if (outputs.length === 0) {
|
|
48
81
|
log.warn(`Transaction ${txHash} has no output to ${recipientAddress}: ${JSON.stringify(tx.vout, null, 2)}`);
|
package/dist/networks/btc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"btc.js","sourceRoot":"","sources":["../../src/networks/btc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"btc.js","sourceRoot":"","sources":["../../src/networks/btc.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Network, TransactionData } from './index.js';
|
|
2
|
-
|
|
2
|
+
import { AttestationCapable, SignatureScheme } from '../attestation.js';
|
|
3
|
+
export declare class CantonNetwork implements Network, AttestationCapable {
|
|
3
4
|
private readonly scanApiUrl;
|
|
4
5
|
private readonly validatorApiUrl;
|
|
5
6
|
private readonly ledgerApiUrl?;
|
|
@@ -7,12 +8,17 @@ export declare class CantonNetwork implements Network {
|
|
|
7
8
|
private readonly daUtilitiesApiUrl;
|
|
8
9
|
private readonly nativeAssetDecimals;
|
|
9
10
|
readonly retryDelay: number;
|
|
11
|
+
readonly signatureScheme = SignatureScheme.Ed25519;
|
|
10
12
|
private readonly clientId?;
|
|
11
13
|
private readonly clientSecret?;
|
|
12
14
|
private readonly senderPartyId?;
|
|
13
15
|
private accessToken?;
|
|
14
16
|
private accessTokenExpiresAt;
|
|
15
17
|
constructor(validatorApiUrl: string, ledgerApiUrl?: string, scanApiUrl?: string, authUrl?: string, clientId?: string, clientSecret?: string, senderPartyId?: string, daUtilitiesApiUrl?: string);
|
|
18
|
+
addressFromPublicKey(publicKey: string): string;
|
|
19
|
+
verifyAttestation(publicKey: string, signature: string, preimage: Uint8Array): Promise<boolean>;
|
|
20
|
+
matchesAddress(publicKey: string, address: string): boolean;
|
|
21
|
+
private hex0x;
|
|
16
22
|
ping(): Promise<void>;
|
|
17
23
|
getDecimals(tokenAddress: string): Promise<number>;
|
|
18
24
|
getTxData(txHash: string, tokenAddress: string): Promise<TransactionData | undefined>;
|
package/dist/networks/canton.js
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import * as ed25519 from '@noble/ed25519';
|
|
2
|
+
import { SignatureScheme, verifyEd25519 } from '../attestation.js';
|
|
2
3
|
import { log, expRetry, memoize } from '../utils.js';
|
|
3
4
|
import { proxyFetch } from '../proxy.js';
|
|
4
5
|
import { Big } from 'big.js';
|
|
5
6
|
import { ethers } from "ethers";
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
// Canton fingerprints are a multihash (0x12 = SHA-256, 0x20 = 32-byte length) over the 4-byte
|
|
9
|
+
// purpose tag 12 (PublicKeyFingerprint) followed by the raw public key bytes.
|
|
10
|
+
const FINGERPRINT_PURPOSE = Buffer.from('0000000c', 'hex');
|
|
11
|
+
const PARTY_ID_PATTERN = /^[\w-]*::(1220[0-9a-fA-F]{64})$/;
|
|
12
|
+
// AttestationCapable via the party-id namespace fingerprint. A Canton "from" is a party-id
|
|
13
|
+
// (`hint::fingerprint`): the hint is free-form and not key-derivable, so sigBound compares
|
|
14
|
+
// fingerprints only (matchesAddress), binding the key to the paying party's NAMESPACE. A delegated,
|
|
15
|
+
// rotated, or multi-controller namespace carries that SAME fingerprint, so it still matches and is
|
|
16
|
+
// NOT auto-excluded here — separating it needs a topology-state lookup we don't do, so such parties
|
|
17
|
+
// must be kept off attested settlement at onboarding. The only fail-closed guards at this layer are
|
|
18
|
+
// the strict PARTY_ID_PATTERN and the 32-byte key-length check.
|
|
6
19
|
export class CantonNetwork {
|
|
7
20
|
constructor(validatorApiUrl, ledgerApiUrl, scanApiUrl, authUrl, clientId, clientSecret, senderPartyId, daUtilitiesApiUrl) {
|
|
8
21
|
this.nativeAssetDecimals = 10;
|
|
9
22
|
this.retryDelay = 5000;
|
|
23
|
+
this.signatureScheme = SignatureScheme.Ed25519;
|
|
10
24
|
this.accessTokenExpiresAt = 0;
|
|
11
25
|
this.validatorApiUrl = validatorApiUrl;
|
|
12
26
|
this.scanApiUrl = scanApiUrl || validatorApiUrl;
|
|
@@ -17,6 +31,25 @@ export class CantonNetwork {
|
|
|
17
31
|
this.clientSecret = clientSecret;
|
|
18
32
|
this.senderPartyId = senderPartyId;
|
|
19
33
|
}
|
|
34
|
+
// Returns the namespace fingerprint, not a full party-id — the hint half is not key-derivable.
|
|
35
|
+
addressFromPublicKey(publicKey) {
|
|
36
|
+
const pub = ethers.getBytes(this.hex0x(publicKey));
|
|
37
|
+
if (pub.length !== 32) {
|
|
38
|
+
throw new Error(`Invalid ed25519 public key length: ${pub.length}`);
|
|
39
|
+
}
|
|
40
|
+
return `1220${createHash('sha256').update(FINGERPRINT_PURPOSE).update(pub).digest('hex')}`;
|
|
41
|
+
}
|
|
42
|
+
verifyAttestation(publicKey, signature, preimage) {
|
|
43
|
+
return verifyEd25519(this.hex0x(publicKey), this.hex0x(signature), preimage);
|
|
44
|
+
}
|
|
45
|
+
matchesAddress(publicKey, address) {
|
|
46
|
+
const partyId = address.match(PARTY_ID_PATTERN);
|
|
47
|
+
return !!partyId && partyId[1].toLowerCase() === this.addressFromPublicKey(publicKey);
|
|
48
|
+
}
|
|
49
|
+
// Canton APIs use bare uppercase hex for keys/signatures; the SDK convention is 0x-prefixed.
|
|
50
|
+
hex0x(hex) {
|
|
51
|
+
return hex.startsWith('0x') ? hex : `0x${hex}`;
|
|
52
|
+
}
|
|
20
53
|
async ping() {
|
|
21
54
|
await this.nodeRequest({ method: 'GET', node: this.ledgerApiUrl, uri: '/v2/version' });
|
|
22
55
|
}
|