@arkade-os/sdk 0.4.54 → 0.4.56
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/adapters/expo.cjs +5 -5
- package/dist/adapters/expo.d.cts +2 -2
- package/dist/adapters/expo.d.ts +2 -2
- package/dist/adapters/expo.js +3 -3
- package/dist/adapters/indexedDB.cjs +5 -5
- package/dist/adapters/indexedDB.js +4 -4
- package/dist/{ark-acFuA57I.d.cts → ark-Cgsd9tMd.d.cts} +40 -3
- package/dist/{ark-acFuA57I.d.ts → ark-Cgsd9tMd.d.ts} +40 -3
- package/dist/{asyncStorageTaskQueue-BO3cvMpP.d.cts → asyncStorageTaskQueue-C0ZsDE60.d.cts} +2 -2
- package/dist/{asyncStorageTaskQueue-DACXtP0I.d.ts → asyncStorageTaskQueue-CXz4PRBW.d.ts} +2 -2
- package/dist/{chunk-RNECH3TA.cjs → chunk-24YNIQSW.cjs} +15 -15
- package/dist/{chunk-RNECH3TA.cjs.map → chunk-24YNIQSW.cjs.map} +1 -1
- package/dist/{chunk-53XNU2EL.cjs → chunk-37XKN5DZ.cjs} +60 -40
- package/dist/chunk-37XKN5DZ.cjs.map +1 -0
- package/dist/{chunk-7L3P3EP5.js → chunk-5IMBONCK.js} +4 -4
- package/dist/{chunk-7L3P3EP5.js.map → chunk-5IMBONCK.js.map} +1 -1
- package/dist/{chunk-GMUVWKOK.cjs → chunk-CDWLZQQW.cjs} +11 -3
- package/dist/chunk-CDWLZQQW.cjs.map +1 -0
- package/dist/{chunk-D5LUPJJP.cjs → chunk-ENRRZFZ4.cjs} +774 -399
- package/dist/chunk-ENRRZFZ4.cjs.map +1 -0
- package/dist/{chunk-4EIKOJLD.js → chunk-IFGN2GB2.js} +11 -4
- package/dist/chunk-IFGN2GB2.js.map +1 -0
- package/dist/{chunk-YRLBZJYO.cjs → chunk-IMVKQQHU.cjs} +9 -9
- package/dist/{chunk-YRLBZJYO.cjs.map → chunk-IMVKQQHU.cjs.map} +1 -1
- package/dist/{chunk-BYJJIITU.cjs → chunk-MXPBHDOI.cjs} +17 -17
- package/dist/{chunk-BYJJIITU.cjs.map → chunk-MXPBHDOI.cjs.map} +1 -1
- package/dist/{chunk-ZOY5JSVA.js → chunk-NN7BNNF5.js} +3 -3
- package/dist/{chunk-ZOY5JSVA.js.map → chunk-NN7BNNF5.js.map} +1 -1
- package/dist/{chunk-A37WVZ5T.js → chunk-OOPDT2WV.js} +23 -4
- package/dist/chunk-OOPDT2WV.js.map +1 -0
- package/dist/{chunk-TEHJCEF3.js → chunk-T22257HW.js} +422 -56
- package/dist/chunk-T22257HW.js.map +1 -0
- package/dist/{chunk-QY2YVFZT.js → chunk-VNDVUM2W.js} +4 -4
- package/dist/{chunk-QY2YVFZT.js.map → chunk-VNDVUM2W.js.map} +1 -1
- package/dist/contracts/handlers/index.cjs +8 -8
- package/dist/contracts/handlers/index.d.cts +3 -3
- package/dist/contracts/handlers/index.d.ts +3 -3
- package/dist/contracts/handlers/index.js +2 -2
- package/dist/{delegate-DjwZZi6L.d.ts → delegate-CZPXtd2F.d.ts} +1 -1
- package/dist/{delegate-Ca_wXiYE.d.cts → delegate-xXT8O-Kn.d.cts} +1 -1
- package/dist/{index-Ddq0mIKX.d.ts → index-BBJ466mM.d.ts} +2 -2
- package/dist/{index-DFfefdpc.d.cts → index-BYG2eKOA.d.cts} +2 -2
- package/dist/index.cjs +246 -202
- package/dist/index.d.cts +169 -16
- package/dist/index.d.ts +169 -16
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +19 -19
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/realm/index.js +5 -5
- package/dist/repositories/sqlite/index.cjs +18 -18
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.js +5 -5
- package/dist/{taskRunner-DEwlrgId.d.cts → taskRunner-BG1PRFps.d.cts} +2 -2
- package/dist/{taskRunner-DbCNRP31.d.ts → taskRunner-C46NnRsY.d.ts} +2 -2
- package/dist/wallet/expo/background.cjs +14 -14
- package/dist/wallet/expo/background.d.cts +3 -3
- package/dist/wallet/expo/background.d.ts +3 -3
- package/dist/wallet/expo/background.js +6 -6
- package/dist/wallet/expo/index.cjs +14 -14
- package/dist/wallet/expo/index.d.cts +5 -5
- package/dist/wallet/expo/index.d.ts +5 -5
- package/dist/wallet/expo/index.js +5 -5
- package/dist/{wallet-B9rpddG2.d.ts → wallet-1yWg75gN.d.cts} +100 -6
- package/dist/{wallet-ByjM6L20.d.cts → wallet-DuCm55EC.d.ts} +100 -6
- package/dist/worker/expo/index.cjs +9 -9
- package/dist/worker/expo/index.d.cts +4 -4
- package/dist/worker/expo/index.d.ts +4 -4
- package/dist/worker/expo/index.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-4EIKOJLD.js.map +0 -1
- package/dist/chunk-53XNU2EL.cjs.map +0 -1
- package/dist/chunk-A37WVZ5T.js.map +0 -1
- package/dist/chunk-D5LUPJJP.cjs.map +0 -1
- package/dist/chunk-GMUVWKOK.cjs.map +0 -1
- package/dist/chunk-TEHJCEF3.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, BufferReader, BufferWriter, AssetRef, RestIndexerProvider } from './chunk-
|
|
2
|
-
import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, DefaultVtxo, speculativeReceiveMetadata, DelegateVtxo,
|
|
3
|
-
import { VtxoScript, Transaction, isRecoverable, CSVMultisigTapscript, DEFAULT_NETWORK, hasTerminalSpend, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, isVirtualCoin, getArkPsbtFields, CosignerPublicKey,
|
|
1
|
+
import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, BufferReader, BufferWriter, AssetRef, RestIndexerProvider } from './chunk-NN7BNNF5.js';
|
|
2
|
+
import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, DefaultVtxo, speculativeReceiveMetadata, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-OOPDT2WV.js';
|
|
3
|
+
import { VtxoScript, Transaction, isRecoverable, CSVMultisigTapscript, DEFAULT_NETWORK, hasTerminalSpend, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, OP_RETURN_EMPTY_PKSCRIPT, sequenceToTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, timelockToSequence, baseFetch, Intent, rateGate, DEFAULT_NETWORK_NAME, normalizeVtxo, getSequence, toBatchExpiry, maybeArkError, isArkError, ArkErrorName, toOffchainInputFeeParams, canRecoverOnchain, getNetwork, MultisigTapscript, isEventSourceError, isRetryableProviderError, getAllNormalizedVtxos, DEFAULT_PAGE_SIZE, RestArkProvider, canSpendOffchain, toVirtualStatus, ArkError, resolveTimeHeight, parseLegacyExpiry, isExpired, DEFAULT_ARKADE_SERVER_URL, ProviderUnavailableError, networks as networks$1, isPastExpiry, fetchVtxoCreatedAtByTxid } from './chunk-IFGN2GB2.js';
|
|
4
4
|
import { __export } from './chunk-NSBPE2FW.js';
|
|
5
5
|
import { sha256, equalBytes, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr } from '@scure/btc-signer/utils.js';
|
|
6
6
|
import { SigHash, Script, OP, OutScript, Address, RawWitness, p2tr, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$2 } from '@scure/btc-signer';
|
|
@@ -517,6 +517,18 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
517
517
|
const key = this.derivePrivateKeyForDescriptor(descriptor);
|
|
518
518
|
return this.signMessageWithKey(key, message, signatureType);
|
|
519
519
|
}
|
|
520
|
+
/**
|
|
521
|
+
* BIP-340 sign `messageHash` with the key derived from `descriptor`,
|
|
522
|
+
* aux_rand = 0. Backs {@link DescriptorIdentity.signSchnorrDeterministic},
|
|
523
|
+
* which swap preimage derivation reads through.
|
|
524
|
+
*/
|
|
525
|
+
async signSchnorrDeterministicWithDescriptor(descriptor, messageHash) {
|
|
526
|
+
if (!this.isOurs(descriptor)) {
|
|
527
|
+
throw new Error(`Descriptor ${descriptor} does not belong to this identity`);
|
|
528
|
+
}
|
|
529
|
+
const key = this.derivePrivateKeyForDescriptor(descriptor);
|
|
530
|
+
return schnorr$1.signAsync(messageHash, key, new Uint8Array(32));
|
|
531
|
+
}
|
|
520
532
|
// ── internal helpers ─────────────────────────────────────────────
|
|
521
533
|
derivePrivateKeyForDescriptor(descriptor) {
|
|
522
534
|
const network = isMainnetDescriptor(descriptor) ? networks.bitcoin : networks.testnet;
|
|
@@ -803,6 +815,59 @@ function assertValidSerializedIdentity(s) {
|
|
|
803
815
|
}
|
|
804
816
|
}
|
|
805
817
|
|
|
818
|
+
// src/identity/descriptorIdentity.ts
|
|
819
|
+
function isHDDeterministicSignCapable(value) {
|
|
820
|
+
return typeof value === "object" && value !== null && typeof value.signSchnorrDeterministicWithDescriptor === "function";
|
|
821
|
+
}
|
|
822
|
+
var DescriptorIdentity = class {
|
|
823
|
+
descriptor;
|
|
824
|
+
signer;
|
|
825
|
+
base;
|
|
826
|
+
constructor({ descriptor, signer, base }) {
|
|
827
|
+
this.descriptor = descriptor;
|
|
828
|
+
this.signer = signer;
|
|
829
|
+
this.base = base;
|
|
830
|
+
}
|
|
831
|
+
async xOnlyPublicKey() {
|
|
832
|
+
return deriveDescriptorLeafPubKey(this.descriptor);
|
|
833
|
+
}
|
|
834
|
+
async compressedPublicKey() {
|
|
835
|
+
return deriveDescriptorLeafCompressedPubKey(this.descriptor);
|
|
836
|
+
}
|
|
837
|
+
async sign(tx, inputIndexes) {
|
|
838
|
+
const [signed] = await this.signer.signWithDescriptor([
|
|
839
|
+
{ descriptor: this.descriptor, tx, inputIndexes }
|
|
840
|
+
]);
|
|
841
|
+
if (!signed) {
|
|
842
|
+
throw new Error(`Descriptor signer returned no transaction for ${this.descriptor}`);
|
|
843
|
+
}
|
|
844
|
+
return signed;
|
|
845
|
+
}
|
|
846
|
+
async signMessage(message, signatureType = "schnorr") {
|
|
847
|
+
return this.signer.signMessageWithDescriptor(this.descriptor, message, signatureType);
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Delegated: `TreeSignerSession.random()` consults no key material, so the
|
|
851
|
+
* session is index-independent.
|
|
852
|
+
*/
|
|
853
|
+
signerSession() {
|
|
854
|
+
return this.base.signerSession();
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Throws rather than falling back to the baseline key: a preimage derived
|
|
858
|
+
* from the wrong index is unrecoverable, and callers probe this member
|
|
859
|
+
* through a structural guard that cannot tell the two apart.
|
|
860
|
+
*/
|
|
861
|
+
async signSchnorrDeterministic(messageHash) {
|
|
862
|
+
if (!isHDDeterministicSignCapable(this.base)) {
|
|
863
|
+
throw new Error(
|
|
864
|
+
`Identity cannot sign deterministically for descriptor ${this.descriptor}`
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
return this.base.signSchnorrDeterministicWithDescriptor(this.descriptor, messageHash);
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
|
|
806
871
|
// src/identity/hdCapableIdentity.ts
|
|
807
872
|
function isHDCapableIdentity(value) {
|
|
808
873
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -815,6 +880,13 @@ function isBatchSignable(identity) {
|
|
|
815
880
|
return "signMultiple" in identity && typeof identity.signMultiple === "function";
|
|
816
881
|
}
|
|
817
882
|
|
|
883
|
+
// src/wallet/hdWalletCapable.ts
|
|
884
|
+
function isHDWalletCapable(value) {
|
|
885
|
+
if (typeof value !== "object" || value === null) return false;
|
|
886
|
+
const v = value;
|
|
887
|
+
return typeof v.getCurrentSigningDescriptor === "function" && typeof v.getUsedSigningDescriptors === "function" && typeof v.signerForDescriptor === "function";
|
|
888
|
+
}
|
|
889
|
+
|
|
818
890
|
// src/worker/browser/service-worker-manager.ts
|
|
819
891
|
var registrations = /* @__PURE__ */ new Map();
|
|
820
892
|
var handshakes = /* @__PURE__ */ new WeakSet();
|
|
@@ -1808,14 +1880,28 @@ function buildOpReturnScript(data) {
|
|
|
1808
1880
|
}
|
|
1809
1881
|
return script;
|
|
1810
1882
|
}
|
|
1811
|
-
var ErrOffchainOutputNotFound = (address) => new
|
|
1812
|
-
var ErrInvalidAssetOutputAmount = (got, want, assetId) => new
|
|
1813
|
-
|
|
1814
|
-
|
|
1883
|
+
var ErrOffchainOutputNotFound = (address) => new ServerResponseMismatchError(`offchain send output not found: ${address}`);
|
|
1884
|
+
var ErrInvalidAssetOutputAmount = (got, want, assetId) => new ServerResponseMismatchError(
|
|
1885
|
+
`invalid asset output amount for ${assetId}: got ${got}, want ${want}`
|
|
1886
|
+
);
|
|
1887
|
+
var ErrAssetGroupNotFound = (assetId) => new ServerResponseMismatchError(`asset group not found in batch leaf: ${assetId}`);
|
|
1888
|
+
var ErrAssetOutputNotFound = (assetId, outputIndex) => new ServerResponseMismatchError(
|
|
1889
|
+
`asset output not found in asset group ${assetId} at index ${outputIndex}`
|
|
1890
|
+
);
|
|
1891
|
+
var ErrOnchainOutputNotFound = (address) => new ServerResponseMismatchError(`onchain output not found: ${address}`);
|
|
1892
|
+
var ErrUnvalidatedOffchainOutput = (address) => new ServerResponseMismatchError(
|
|
1893
|
+
`offchain output ${address} cannot be validated: virtual output tree signing did not run`
|
|
1894
|
+
);
|
|
1815
1895
|
var ErrInvalidOnchainOutputAmount = (address) => new Error(`invalid onchain output amount: ${address}`);
|
|
1816
1896
|
var ErrInvalidOnchainOutputAssets = (address) => new Error(`onchain output ${address} cannot have assets`);
|
|
1817
|
-
var ErrOnchainOutputNotFound = (address) => new Error(`onchain output not found: ${address}`);
|
|
1818
1897
|
var ErrInvalidOffchainOutputAmount = (address) => new Error(`invalid offchain output ${address}, missing amount`);
|
|
1898
|
+
function assertFinalCommitmentMatchesValidated(finalCommitmentTx, validatedCommitmentTxid, context) {
|
|
1899
|
+
if (!validatedCommitmentTxid) return;
|
|
1900
|
+
if (finalCommitmentTx.id === validatedCommitmentTxid) return;
|
|
1901
|
+
throw new ServerResponseMismatchError(
|
|
1902
|
+
`${context}: finalization commitment tx ${finalCommitmentTx.id} differs from the validated commitment tx ${validatedCommitmentTxid}`
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1819
1905
|
function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, network) {
|
|
1820
1906
|
const usedOutputs = /* @__PURE__ */ new Set();
|
|
1821
1907
|
const usedOnchainOutputs = /* @__PURE__ */ new Set();
|
|
@@ -1830,6 +1916,18 @@ function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, netwo
|
|
|
1830
1916
|
validateOffchainRecipient(vtxoTreeLeaves, arkAddress, recipient, usedOutputs);
|
|
1831
1917
|
}
|
|
1832
1918
|
}
|
|
1919
|
+
function validateBatchRecipientsWithoutTree(commitmentTx, recipients, network) {
|
|
1920
|
+
const usedOnchainOutputs = /* @__PURE__ */ new Set();
|
|
1921
|
+
for (const recipient of recipients) {
|
|
1922
|
+
try {
|
|
1923
|
+
ArkAddress.decode(recipient.address);
|
|
1924
|
+
} catch {
|
|
1925
|
+
validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
|
|
1926
|
+
continue;
|
|
1927
|
+
}
|
|
1928
|
+
throw ErrUnvalidatedOffchainOutput(recipient.address);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1833
1931
|
function validateOnchainRecipient(commitmentTx, recipient, network, usedOutputs) {
|
|
1834
1932
|
const addr = Address(network).decode(recipient.address);
|
|
1835
1933
|
const expectedPkScript = OutScript.encode(addr);
|
|
@@ -1922,8 +2020,6 @@ function validateAssetGroupOutput(packet, outputIndex, assetId, expectedAmount)
|
|
|
1922
2020
|
throw ErrInvalidAssetOutputAmount(assetOutput.amount, expectedAmount, assetId);
|
|
1923
2021
|
}
|
|
1924
2022
|
}
|
|
1925
|
-
|
|
1926
|
-
// src/wallet/activity.ts
|
|
1927
2023
|
async function buildActivities(txs, resolvers) {
|
|
1928
2024
|
const preparedResolvers = (await Promise.all(
|
|
1929
2025
|
resolvers.map(async (r) => {
|
|
@@ -2033,9 +2129,49 @@ function boardingResolver() {
|
|
|
2033
2129
|
}
|
|
2034
2130
|
};
|
|
2035
2131
|
}
|
|
2132
|
+
function collabExitResolver() {
|
|
2133
|
+
return {
|
|
2134
|
+
id: "collab-exit",
|
|
2135
|
+
resolve(tx) {
|
|
2136
|
+
if (tx.tag !== "exit" || !tx.key.commitmentTxid) return void 0;
|
|
2137
|
+
return [
|
|
2138
|
+
{
|
|
2139
|
+
groupId: `exit:${tx.key.commitmentTxid}`,
|
|
2140
|
+
label: "Collaborative exit",
|
|
2141
|
+
kind: "exit"
|
|
2142
|
+
}
|
|
2143
|
+
];
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
function assetMintResolver() {
|
|
2148
|
+
return {
|
|
2149
|
+
id: "asset-mint",
|
|
2150
|
+
resolve(tx) {
|
|
2151
|
+
if (!tx.assets?.length || !tx.key.arkTxid) return void 0;
|
|
2152
|
+
const minted = tx.assets.filter((a) => {
|
|
2153
|
+
try {
|
|
2154
|
+
return hex.encode(AssetId.fromString(a.assetId).txid) === tx.key.arkTxid;
|
|
2155
|
+
} catch {
|
|
2156
|
+
return false;
|
|
2157
|
+
}
|
|
2158
|
+
});
|
|
2159
|
+
if (minted.length === 0) return void 0;
|
|
2160
|
+
const received = tx.type === "RECEIVED" /* TxReceived */;
|
|
2161
|
+
return minted.map((a) => ({
|
|
2162
|
+
groupId: `mint:${a.assetId}`,
|
|
2163
|
+
label: received ? "Asset receive" : "Asset mint",
|
|
2164
|
+
kind: received ? "asset-receive" : "asset-mint",
|
|
2165
|
+
metadata: { assetId: a.assetId, amount: a.amount.toString() }
|
|
2166
|
+
}));
|
|
2167
|
+
}
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2036
2170
|
function createDefaultActivityRegistry() {
|
|
2037
2171
|
const registry = new ActivityRegistry();
|
|
2038
2172
|
registry.use(boardingResolver());
|
|
2173
|
+
registry.use(collabExitResolver());
|
|
2174
|
+
registry.use(assetMintResolver());
|
|
2039
2175
|
return registry;
|
|
2040
2176
|
}
|
|
2041
2177
|
|
|
@@ -2395,6 +2531,70 @@ function isValidArkAddress(address) {
|
|
|
2395
2531
|
return false;
|
|
2396
2532
|
}
|
|
2397
2533
|
}
|
|
2534
|
+
function matchServerCheckpoints(serverCheckpointTxs, expectedCheckpoints, context) {
|
|
2535
|
+
if (serverCheckpointTxs.length !== expectedCheckpoints.length) {
|
|
2536
|
+
throw new ServerResponseMismatchError(
|
|
2537
|
+
`${context} returned ${serverCheckpointTxs.length} checkpoints, expected ${expectedCheckpoints.length}`
|
|
2538
|
+
);
|
|
2539
|
+
}
|
|
2540
|
+
const byTxid = new Map(expectedCheckpoints.map((c) => [c.id, c]));
|
|
2541
|
+
return serverCheckpointTxs.map((encoded, index) => {
|
|
2542
|
+
const server = Transaction.fromPSBT(base64.decode(encoded));
|
|
2543
|
+
const local = byTxid.get(server.id);
|
|
2544
|
+
if (!local) {
|
|
2545
|
+
throw new ServerResponseMismatchError(
|
|
2546
|
+
`${context} checkpoint ${index} txid ${server.id} does not match any submitted checkpoint`
|
|
2547
|
+
);
|
|
2548
|
+
}
|
|
2549
|
+
byTxid.delete(server.id);
|
|
2550
|
+
return { server, local };
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
function assertSubmittedArkTxid(response, signedArkTx, context) {
|
|
2554
|
+
if (response.arkTxid !== signedArkTx.id) {
|
|
2555
|
+
throw new ServerResponseMismatchError(
|
|
2556
|
+
`${context} returned ark txid ${response.arkTxid}, expected ${signedArkTx.id}`
|
|
2557
|
+
);
|
|
2558
|
+
}
|
|
2559
|
+
if (response.finalArkTx === void 0) return;
|
|
2560
|
+
const finalTxid = Transaction.fromPSBT(base64.decode(response.finalArkTx)).id;
|
|
2561
|
+
if (finalTxid !== signedArkTx.id) {
|
|
2562
|
+
throw new ServerResponseMismatchError(
|
|
2563
|
+
`${context} returned final ark tx ${finalTxid}, expected ${signedArkTx.id}`
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
function assertCheckpointsMatchInputs(checkpoints, inputs, unrollCandidates, context) {
|
|
2568
|
+
const byOutpoint = new Map(inputs.map((input) => [`${input.txid}:${input.vout}`, input]));
|
|
2569
|
+
for (const [index, checkpoint] of checkpoints.entries()) {
|
|
2570
|
+
if (checkpoint.inputsLength !== 1) {
|
|
2571
|
+
throw new ServerResponseMismatchError(
|
|
2572
|
+
`${context}: checkpoint ${index} spends ${checkpoint.inputsLength} inputs, expected 1`
|
|
2573
|
+
);
|
|
2574
|
+
}
|
|
2575
|
+
const spent = checkpoint.getInput(0);
|
|
2576
|
+
if (!spent.txid || spent.index === void 0) {
|
|
2577
|
+
throw new ServerResponseMismatchError(
|
|
2578
|
+
`${context}: checkpoint ${index} has no input outpoint`
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2581
|
+
const outpoint = `${hex.encode(spent.txid)}:${spent.index}`;
|
|
2582
|
+
const input = byOutpoint.get(outpoint);
|
|
2583
|
+
if (!input) {
|
|
2584
|
+
throw new ServerResponseMismatchError(
|
|
2585
|
+
`${context}: checkpoint ${index} spends ${outpoint}, which is not one of the requested virtual outputs`
|
|
2586
|
+
);
|
|
2587
|
+
}
|
|
2588
|
+
const rebuilt = unrollCandidates.some(
|
|
2589
|
+
(unroll) => buildCheckpointTx(input, unroll).tx.id === checkpoint.id
|
|
2590
|
+
);
|
|
2591
|
+
if (!rebuilt) {
|
|
2592
|
+
throw new ServerResponseMismatchError(
|
|
2593
|
+
`${context}: checkpoint ${index} txid ${checkpoint.id} differs from the checkpoint built locally for ${outpoint}`
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2398
2598
|
async function submitOffchainTx(provider, offchainTx, signer, hooks) {
|
|
2399
2599
|
const { arkTx: signedArkTx, userSignedCheckpoints } = await signer.signArkTx(
|
|
2400
2600
|
offchainTx.arkTx,
|
|
@@ -2406,27 +2606,26 @@ async function submitOffchainTx(provider, offchainTx, signer, hooks) {
|
|
|
2406
2606
|
);
|
|
2407
2607
|
}
|
|
2408
2608
|
await hooks?.beforeSubmit?.();
|
|
2409
|
-
const
|
|
2609
|
+
const response = await provider.submitTx(
|
|
2410
2610
|
base64.encode(signedArkTx.toPSBT()),
|
|
2411
2611
|
offchainTx.checkpoints.map((c) => base64.encode(c.toPSBT()))
|
|
2412
2612
|
);
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
);
|
|
2417
|
-
}
|
|
2613
|
+
assertSubmittedArkTxid(response, signedArkTx, "submitTx");
|
|
2614
|
+
const { arkTxid, signedCheckpointTxs } = response;
|
|
2615
|
+
const matched = matchServerCheckpoints(signedCheckpointTxs, offchainTx.checkpoints, "submitTx");
|
|
2418
2616
|
let finalCheckpoints;
|
|
2419
2617
|
if (userSignedCheckpoints) {
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2618
|
+
const userByTxid = new Map(
|
|
2619
|
+
userSignedCheckpoints.map((c, i) => [offchainTx.checkpoints[i].id, c])
|
|
2620
|
+
);
|
|
2621
|
+
finalCheckpoints = matched.map(({ server, local }) => {
|
|
2622
|
+
combineTapscriptSigs(userByTxid.get(local.id), server);
|
|
2623
|
+
return base64.encode(server.toPSBT());
|
|
2424
2624
|
});
|
|
2425
2625
|
} else {
|
|
2426
2626
|
finalCheckpoints = await Promise.all(
|
|
2427
|
-
|
|
2428
|
-
const
|
|
2429
|
-
const signed = await signer.signCheckpoint(tx);
|
|
2627
|
+
matched.map(async ({ server }) => {
|
|
2628
|
+
const signed = await signer.signCheckpoint(server);
|
|
2430
2629
|
return base64.encode(signed.toPSBT());
|
|
2431
2630
|
})
|
|
2432
2631
|
);
|
|
@@ -2701,7 +2900,26 @@ function isValidArkAddress2(address) {
|
|
|
2701
2900
|
return false;
|
|
2702
2901
|
}
|
|
2703
2902
|
}
|
|
2704
|
-
function
|
|
2903
|
+
function assertRecipientArkAddress(encoded, address, context) {
|
|
2904
|
+
if (address.hrp !== context.hrp) {
|
|
2905
|
+
throw new Error(
|
|
2906
|
+
`Invalid Arkade address ${encoded}: expected prefix "${context.hrp}", got "${address.hrp}"`
|
|
2907
|
+
);
|
|
2908
|
+
}
|
|
2909
|
+
const { status } = classifyAgainstSignerSet(
|
|
2910
|
+
hex.encode(address.serverPubKey),
|
|
2911
|
+
context.signerSet
|
|
2912
|
+
);
|
|
2913
|
+
if (status === "UNKNOWN_SIGNER") {
|
|
2914
|
+
throw new Error(`Invalid Arkade address ${encoded}: unknown operator signer key`);
|
|
2915
|
+
}
|
|
2916
|
+
if (status === "EXPIRED") {
|
|
2917
|
+
throw new Error(
|
|
2918
|
+
`Invalid Arkade address ${encoded}: operator signer key is past its rotation cutoff`
|
|
2919
|
+
);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
function validateRecipients(recipients, dustAmount, context) {
|
|
2705
2923
|
const validatedRecipients = [];
|
|
2706
2924
|
for (const recipient of recipients) {
|
|
2707
2925
|
let address;
|
|
@@ -2710,6 +2928,7 @@ function validateRecipients(recipients, dustAmount) {
|
|
|
2710
2928
|
} catch (e) {
|
|
2711
2929
|
throw new Error(`Invalid Arkade address: ${recipient.address}`);
|
|
2712
2930
|
}
|
|
2931
|
+
assertRecipientArkAddress(recipient.address, address, context);
|
|
2713
2932
|
const amount = recipient.amount || dustAmount;
|
|
2714
2933
|
if (amount <= 0) {
|
|
2715
2934
|
throw new Error("Amount must be positive");
|
|
@@ -10775,6 +10994,20 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10775
10994
|
...this._deprecatedSigners.keys()
|
|
10776
10995
|
]);
|
|
10777
10996
|
}
|
|
10997
|
+
/**
|
|
10998
|
+
* `serverPubKey` defaults to the live key; spend paths that snapshot it
|
|
10999
|
+
* against mid-flight rotation pass their snapshot, so the check reads from
|
|
11000
|
+
* one rotation epoch.
|
|
11001
|
+
*/
|
|
11002
|
+
recipientAddressContext(serverPubKey = this._arkServerPublicKey) {
|
|
11003
|
+
return {
|
|
11004
|
+
hrp: this.network.hrp,
|
|
11005
|
+
signerSet: {
|
|
11006
|
+
active: toXOnlySignerHex(hex.encode(serverPubKey)),
|
|
11007
|
+
deprecated: this._deprecatedSigners
|
|
11008
|
+
}
|
|
11009
|
+
};
|
|
11010
|
+
}
|
|
10778
11011
|
/**
|
|
10779
11012
|
* Currently-active receive tapscript. Read-only from the outside;
|
|
10780
11013
|
* mutated only via {@link Wallet.setOffchainTapscriptForRotation}
|
|
@@ -11952,6 +12185,51 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11952
12185
|
}
|
|
11953
12186
|
return newBoarding.onchainAddress(this.network);
|
|
11954
12187
|
}
|
|
12188
|
+
/**
|
|
12189
|
+
* @see HDWalletCapable.getCurrentSigningDescriptor
|
|
12190
|
+
*/
|
|
12191
|
+
async getCurrentSigningDescriptor() {
|
|
12192
|
+
const provider = this._descriptorProvider;
|
|
12193
|
+
if (!(provider instanceof HDDescriptorProvider)) return void 0;
|
|
12194
|
+
return provider.getCurrentSigningDescriptor();
|
|
12195
|
+
}
|
|
12196
|
+
/**
|
|
12197
|
+
* @see HDWalletCapable.getUsedSigningDescriptors
|
|
12198
|
+
*
|
|
12199
|
+
* Union of the watermark band and the descriptors persisted on contracts:
|
|
12200
|
+
* the band alone would miss rows a restore scan wrote, and the contracts
|
|
12201
|
+
* alone would miss indices allocated for something the wallet never
|
|
12202
|
+
* persisted (a swap, an externally issued invoice).
|
|
12203
|
+
*/
|
|
12204
|
+
async getUsedSigningDescriptors() {
|
|
12205
|
+
const provider = this._descriptorProvider;
|
|
12206
|
+
const descriptors = /* @__PURE__ */ new Set();
|
|
12207
|
+
if (provider instanceof HDDescriptorProvider) {
|
|
12208
|
+
const lastIndexUsed = await provider.getLastIndexUsed();
|
|
12209
|
+
for (let i = 0; i <= (lastIndexUsed ?? -1); i++) {
|
|
12210
|
+
descriptors.add(provider.materializeDescriptorAt(i));
|
|
12211
|
+
}
|
|
12212
|
+
}
|
|
12213
|
+
for (const contract of await this.contractRepository.getContracts()) {
|
|
12214
|
+
const descriptor = contract.metadata?.signingDescriptor;
|
|
12215
|
+
if (typeof descriptor === "string" && descriptor.length > 0) {
|
|
12216
|
+
descriptors.add(descriptor);
|
|
12217
|
+
}
|
|
12218
|
+
}
|
|
12219
|
+
return [...descriptors].sort(
|
|
12220
|
+
(a, b) => signingDescriptorIndex(a) - signingDescriptorIndex(b)
|
|
12221
|
+
);
|
|
12222
|
+
}
|
|
12223
|
+
/**
|
|
12224
|
+
* @see HDWalletCapable.signerForDescriptor
|
|
12225
|
+
*/
|
|
12226
|
+
async signerForDescriptor(descriptor) {
|
|
12227
|
+
const provider = this._descriptorProvider;
|
|
12228
|
+
if (!(provider instanceof HDDescriptorProvider) || !provider.isOurs(descriptor)) {
|
|
12229
|
+
return this.identity;
|
|
12230
|
+
}
|
|
12231
|
+
return new DescriptorIdentity({ descriptor, signer: provider, base: this.identity });
|
|
12232
|
+
}
|
|
11955
12233
|
/**
|
|
11956
12234
|
* Mid-session server-signer rotation (plan §4). When arkd rotates its
|
|
11957
12235
|
* active signer mid-session — the case the long-lived service worker and
|
|
@@ -12435,6 +12713,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12435
12713
|
changeAmount: BigInt(changeAmount)
|
|
12436
12714
|
};
|
|
12437
12715
|
const outputAddress = ArkAddress.decode(params.address);
|
|
12716
|
+
assertRecipientArkAddress(
|
|
12717
|
+
params.address,
|
|
12718
|
+
outputAddress,
|
|
12719
|
+
this.recipientAddressContext(serverPubKey)
|
|
12720
|
+
);
|
|
12438
12721
|
const outputScript = BigInt(params.amount) < this.dustAmount ? outputAddress.subdustPkScript : outputAddress.pkScript;
|
|
12439
12722
|
const outputs = [
|
|
12440
12723
|
{
|
|
@@ -12564,13 +12847,21 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12564
12847
|
const onchainOutputIndexes = [];
|
|
12565
12848
|
const outputs = [];
|
|
12566
12849
|
let hasOffchainOutputs = false;
|
|
12850
|
+
let recipientContext;
|
|
12567
12851
|
for (const [index, output] of params.outputs.entries()) {
|
|
12568
12852
|
let script;
|
|
12853
|
+
let arkAddress;
|
|
12569
12854
|
try {
|
|
12570
|
-
|
|
12571
|
-
script = addr.pkScript;
|
|
12572
|
-
hasOffchainOutputs = true;
|
|
12855
|
+
arkAddress = ArkAddress.decode(output.address);
|
|
12573
12856
|
} catch {
|
|
12857
|
+
arkAddress = void 0;
|
|
12858
|
+
}
|
|
12859
|
+
if (arkAddress) {
|
|
12860
|
+
recipientContext ??= this.recipientAddressContext();
|
|
12861
|
+
assertRecipientArkAddress(output.address, arkAddress, recipientContext);
|
|
12862
|
+
script = arkAddress.pkScript;
|
|
12863
|
+
hasOffchainOutputs = true;
|
|
12864
|
+
} else {
|
|
12574
12865
|
const addr = Address(this.network).decode(output.address);
|
|
12575
12866
|
script = OutScript.encode(addr);
|
|
12576
12867
|
onchainOutputIndexes.push(index);
|
|
@@ -12762,9 +13053,17 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12762
13053
|
console.warn("Failed to rotate boarding address after board", e);
|
|
12763
13054
|
}
|
|
12764
13055
|
}
|
|
12765
|
-
async handleSettlementFinalizationEvent(event, inputs, forfeitOutputScript, connectorsGraph) {
|
|
13056
|
+
async handleSettlementFinalizationEvent(event, inputs, forfeitOutputScript, expectedRecipients, connectorsGraph, validatedCommitmentTxid) {
|
|
12766
13057
|
const signedForfeits = [];
|
|
12767
13058
|
let settlementPsbt = Transaction$2.fromPSBT(base64.decode(event.commitmentTx));
|
|
13059
|
+
assertFinalCommitmentMatchesValidated(
|
|
13060
|
+
settlementPsbt,
|
|
13061
|
+
validatedCommitmentTxid,
|
|
13062
|
+
"settlement finalization"
|
|
13063
|
+
);
|
|
13064
|
+
if (!validatedCommitmentTxid && expectedRecipients.length > 0) {
|
|
13065
|
+
validateBatchRecipientsWithoutTree(settlementPsbt, expectedRecipients, this.network);
|
|
13066
|
+
}
|
|
12768
13067
|
let hasBoardingUtxos = false;
|
|
12769
13068
|
let connectorIndex = 0;
|
|
12770
13069
|
const connectorsLeaves = connectorsGraph?.leaves() || [];
|
|
@@ -12887,6 +13186,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12887
13186
|
*/
|
|
12888
13187
|
createBatchHandler(intentId, inputs, expectedRecipients, session) {
|
|
12889
13188
|
let sweepTapTreeRoot;
|
|
13189
|
+
let validatedCommitmentTxid;
|
|
12890
13190
|
return {
|
|
12891
13191
|
onBatchStarted: async (event) => {
|
|
12892
13192
|
const utf8IntentId = new TextEncoder().encode(intentId);
|
|
@@ -12944,6 +13244,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12944
13244
|
if (!sharedOutput?.amount) {
|
|
12945
13245
|
throw new Error("Shared output not found");
|
|
12946
13246
|
}
|
|
13247
|
+
validatedCommitmentTxid = commitmentTx.id;
|
|
12947
13248
|
await session.init(vtxoTree, sweepTapTreeRoot, sharedOutput.amount);
|
|
12948
13249
|
const pubkey = hex.encode(await session.getPublicKey());
|
|
12949
13250
|
const nonces = await session.getNonces();
|
|
@@ -12972,7 +13273,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12972
13273
|
event,
|
|
12973
13274
|
inputs,
|
|
12974
13275
|
this.forfeitOutputScript,
|
|
12975
|
-
|
|
13276
|
+
expectedRecipients,
|
|
13277
|
+
connectorTree,
|
|
13278
|
+
validatedCommitmentTxid
|
|
12976
13279
|
);
|
|
12977
13280
|
}
|
|
12978
13281
|
};
|
|
@@ -13131,6 +13434,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13131
13434
|
for (let i = 0; i < vtxos.length; i += MAX_INPUTS_PER_INTENT) {
|
|
13132
13435
|
batches.push(vtxos.slice(i, i + MAX_INPUTS_PER_INTENT));
|
|
13133
13436
|
}
|
|
13437
|
+
const unrollCandidates = this.checkpointUnrollCandidates(await this.arkProvider.getInfo());
|
|
13438
|
+
const checkpointInputs = vtxos.map((vtxo) => ({
|
|
13439
|
+
...vtxo,
|
|
13440
|
+
tapLeafScript: vtxo.forfeitTapLeafScript
|
|
13441
|
+
}));
|
|
13134
13442
|
const seen = /* @__PURE__ */ new Set();
|
|
13135
13443
|
const results = await Promise.all(
|
|
13136
13444
|
batches.map(async (batch) => {
|
|
@@ -13146,6 +13454,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13146
13454
|
const checkpointTxs = pendingTx.signedCheckpointTxs.map(
|
|
13147
13455
|
(c) => Transaction$2.fromPSBT(base64.decode(c))
|
|
13148
13456
|
);
|
|
13457
|
+
assertCheckpointsMatchInputs(
|
|
13458
|
+
checkpointTxs,
|
|
13459
|
+
checkpointInputs,
|
|
13460
|
+
unrollCandidates,
|
|
13461
|
+
`pending tx ${pendingTx.arkTxid}`
|
|
13462
|
+
);
|
|
13149
13463
|
const checkpointJobs = checkpointTxs.map(
|
|
13150
13464
|
(tx) => this.inputSigningJobsFromWitnessUtxos(tx)
|
|
13151
13465
|
);
|
|
@@ -13201,6 +13515,32 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13201
13515
|
}
|
|
13202
13516
|
return { finalized, pending };
|
|
13203
13517
|
}
|
|
13518
|
+
/**
|
|
13519
|
+
* The server unroll scripts a pending checkpoint may legitimately have been
|
|
13520
|
+
* built under: this wallet's configured one, the server's current one, and
|
|
13521
|
+
* one per deprecated signer (same closure, deprecated key). A tx submitted
|
|
13522
|
+
* before a signer rotation was built under the old key, so rebuilding
|
|
13523
|
+
* against the current key alone would leave it pending forever.
|
|
13524
|
+
*/
|
|
13525
|
+
checkpointUnrollCandidates(info) {
|
|
13526
|
+
const current = CSVMultisigTapscript.decode(hex.decode(info.checkpointTapscript));
|
|
13527
|
+
const candidates = [this._serverUnrollScript, current];
|
|
13528
|
+
for (const deprecated of signerSetFromInfo(info).deprecated.keys()) {
|
|
13529
|
+
candidates.push(
|
|
13530
|
+
CSVMultisigTapscript.encode({
|
|
13531
|
+
...current.params,
|
|
13532
|
+
pubkeys: [hex.decode(deprecated)]
|
|
13533
|
+
})
|
|
13534
|
+
);
|
|
13535
|
+
}
|
|
13536
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13537
|
+
return candidates.filter((candidate) => {
|
|
13538
|
+
const script = hex.encode(candidate.script);
|
|
13539
|
+
if (seen.has(script)) return false;
|
|
13540
|
+
seen.add(script);
|
|
13541
|
+
return true;
|
|
13542
|
+
});
|
|
13543
|
+
}
|
|
13204
13544
|
async hasPendingTxFlag() {
|
|
13205
13545
|
const state = await this.walletRepository.getWalletState();
|
|
13206
13546
|
return state?.settings?.hasPendingTx === true;
|
|
@@ -13433,12 +13773,23 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13433
13773
|
pendingTxs.push(pendingTx);
|
|
13434
13774
|
}
|
|
13435
13775
|
}
|
|
13776
|
+
if (pendingTxs.length === 0) return result;
|
|
13436
13777
|
const myPkScriptHex = hex.encode(myPkScript);
|
|
13778
|
+
const unrollCandidates = this.checkpointUnrollCandidates(await this.arkProvider.getInfo());
|
|
13437
13779
|
for (const pendingTx of pendingTxs) {
|
|
13438
13780
|
try {
|
|
13439
13781
|
const checkpointTxs = pendingTx.signedCheckpointTxs.map(
|
|
13440
13782
|
(checkpoint) => Transaction$2.fromPSBT(base64.decode(checkpoint))
|
|
13441
13783
|
);
|
|
13784
|
+
assertCheckpointsMatchInputs(
|
|
13785
|
+
checkpointTxs,
|
|
13786
|
+
inputs.map((input) => ({
|
|
13787
|
+
...input,
|
|
13788
|
+
tapLeafScript: input.forfeitTapLeafScript
|
|
13789
|
+
})),
|
|
13790
|
+
unrollCandidates,
|
|
13791
|
+
`pending arkadeCash tx ${pendingTx.arkTxid}`
|
|
13792
|
+
);
|
|
13442
13793
|
const finalCheckpoints = await Promise.all(
|
|
13443
13794
|
checkpointTxs.map(
|
|
13444
13795
|
async (checkpoint) => base64.encode((await identity.sign(checkpoint)).toPSBT())
|
|
@@ -13503,7 +13854,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13503
13854
|
const serverUnrollScript = this.serverUnrollScript;
|
|
13504
13855
|
const outputAddress = offchainTapscript.address(this.network.hrp, serverPubKey);
|
|
13505
13856
|
const address = outputAddress.encode();
|
|
13506
|
-
const recipients = validateRecipients(
|
|
13857
|
+
const recipients = validateRecipients(
|
|
13858
|
+
args,
|
|
13859
|
+
Number(this.dustAmount),
|
|
13860
|
+
this.recipientAddressContext(serverPubKey)
|
|
13861
|
+
);
|
|
13507
13862
|
const allVirtualCoins = await this.getVtxos({
|
|
13508
13863
|
withRecoverable: false
|
|
13509
13864
|
});
|
|
@@ -13848,28 +14203,29 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13848
14203
|
`updateDbAfterOffchainTx: inputs length (${inputs.length}) differs from signedCheckpointTxs length (${signedCheckpointTxs.length})`
|
|
13849
14204
|
);
|
|
13850
14205
|
}
|
|
13851
|
-
const
|
|
14206
|
+
const checkpointIdByOutpoint = /* @__PURE__ */ new Map();
|
|
14207
|
+
for (const encoded of signedCheckpointTxs) {
|
|
14208
|
+
const checkpoint = Transaction$2.fromPSBT(base64.decode(encoded));
|
|
14209
|
+
for (let i = 0; i < checkpoint.inputsLength; i++) {
|
|
14210
|
+
const input = checkpoint.getInput(i);
|
|
14211
|
+
if (!input.txid) continue;
|
|
14212
|
+
checkpointIdByOutpoint.set(
|
|
14213
|
+
`${hex.encode(input.txid)}:${input.index}`,
|
|
14214
|
+
checkpoint.id
|
|
14215
|
+
);
|
|
14216
|
+
}
|
|
14217
|
+
}
|
|
13852
14218
|
const cm = await this.getContractManager();
|
|
13853
14219
|
const annotatedInputs = await cm.annotateVtxos(inputs);
|
|
13854
|
-
for (const
|
|
14220
|
+
for (const vtxo of annotatedInputs) {
|
|
13855
14221
|
const spentFacts = { ...vtxo, isSpent: true };
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
)
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
spentBy: checkpoint.id,
|
|
13864
|
-
arkTxId: arkTxid
|
|
13865
|
-
});
|
|
13866
|
-
} else {
|
|
13867
|
-
spentVtxos.push({
|
|
13868
|
-
...spentFacts,
|
|
13869
|
-
virtualStatus: toVirtualStatus(spentFacts),
|
|
13870
|
-
arkTxId: arkTxid
|
|
13871
|
-
});
|
|
13872
|
-
}
|
|
14222
|
+
const spentBy = checkpointIdByOutpoint.get(`${vtxo.txid}:${vtxo.vout}`);
|
|
14223
|
+
spentVtxos.push({
|
|
14224
|
+
...spentFacts,
|
|
14225
|
+
virtualStatus: toVirtualStatus(spentFacts),
|
|
14226
|
+
...spentBy ? { spentBy } : {},
|
|
14227
|
+
arkTxId: arkTxid
|
|
14228
|
+
});
|
|
13873
14229
|
for (const id of vtxo.commitmentTxIds) {
|
|
13874
14230
|
commitmentTxIds.add(id);
|
|
13875
14231
|
}
|
|
@@ -19528,6 +19884,7 @@ var isVtxoCoin = (input) => isVirtualCoin(input);
|
|
|
19528
19884
|
function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message, session, arkProvider, emulator, network, recipients) {
|
|
19529
19885
|
let batchId;
|
|
19530
19886
|
let sweepTapTreeRoot;
|
|
19887
|
+
let validatedCommitmentTxid;
|
|
19531
19888
|
return {
|
|
19532
19889
|
onBatchStarted: async (event) => {
|
|
19533
19890
|
const utf8IntentId = new TextEncoder().encode(intentId);
|
|
@@ -19563,6 +19920,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
19563
19920
|
if (!sharedOutput?.amount) {
|
|
19564
19921
|
throw new Error("Shared output not found");
|
|
19565
19922
|
}
|
|
19923
|
+
validatedCommitmentTxid = commitmentTx.id;
|
|
19566
19924
|
await session.init(vtxoTree, sweepTapTreeRoot, sharedOutput.amount);
|
|
19567
19925
|
const pubkey = hex.encode(await session.getPublicKey());
|
|
19568
19926
|
const nonces = await session.getNonces();
|
|
@@ -19586,6 +19944,14 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
19586
19944
|
validateConnectorsTxGraph(event.commitmentTx, connectorTree);
|
|
19587
19945
|
}
|
|
19588
19946
|
let commitmentPsbt = Transaction.fromPSBT(base64.decode(event.commitmentTx));
|
|
19947
|
+
assertFinalCommitmentMatchesValidated(
|
|
19948
|
+
commitmentPsbt,
|
|
19949
|
+
validatedCommitmentTxid,
|
|
19950
|
+
"arkade batch finalization"
|
|
19951
|
+
);
|
|
19952
|
+
if (!validatedCommitmentTxid && recipients && recipients.length > 0) {
|
|
19953
|
+
validateBatchRecipientsWithoutTree(commitmentPsbt, recipients, network);
|
|
19954
|
+
}
|
|
19589
19955
|
const signedForfeits = [];
|
|
19590
19956
|
let connectorIndex = 0;
|
|
19591
19957
|
const connectorLeaves = connectorTree?.leaves() || [];
|
|
@@ -20052,11 +20418,11 @@ var ArkadeTransactionBuilder = class {
|
|
|
20052
20418
|
base64.encode(signedArk.toPSBT()),
|
|
20053
20419
|
checkpoints.map((c) => base64.encode(c.toPSBT()))
|
|
20054
20420
|
);
|
|
20421
|
+
assertSubmittedArkTxid(res, signedArk, "submitTx");
|
|
20422
|
+
const matched = matchServerCheckpoints(res.signedCheckpointTxs, checkpoints, "submitTx");
|
|
20055
20423
|
const finalCps = await Promise.all(
|
|
20056
|
-
|
|
20057
|
-
async (
|
|
20058
|
-
(await client.identity.sign(Transaction.fromPSBT(base64.decode(b)), [0])).toPSBT()
|
|
20059
|
-
)
|
|
20424
|
+
matched.map(
|
|
20425
|
+
async ({ server }) => base64.encode((await client.identity.sign(server, [0])).toPSBT())
|
|
20060
20426
|
)
|
|
20061
20427
|
);
|
|
20062
20428
|
await client.arkProvider.finalizeTx(res.arkTxid, finalCps);
|
|
@@ -20553,6 +20919,6 @@ function isArkContract(str) {
|
|
|
20553
20919
|
return str.startsWith(ARKCONTRACT_PREFIX + "=");
|
|
20554
20920
|
}
|
|
20555
20921
|
|
|
20556
|
-
export { ARKADE_MAGIC, ActivityRegistry, AmbiguousRouteError, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP21, BIP21Error, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EmulatorPacket, EsploraProvider, Estimator, Extension, ExtensionNotFoundError, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, PaymentRouter, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, RestEmulatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, UnilateralExit, UnknownPacket, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, arkRail, arkTarget, arkade_exports, assertIntentIdUnique, assertSendableAmount, boardingResolver, btcTarget, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createAssetPacket, createDefaultActivityRegistry, createDefaultPaymentRouter, createExitChainResolver, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, hasCandidates, intentMatchesFilter, intentPageBounds, invoiceTarget, isArkContract, isBatchSignable, isBtcAddress, isCooperativelyMigratable, isDiscoverable, isLightningInvoice, isLnurl, isMessageBusInitializingError, isMessageBusNotInitializedError, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, makeHandle, mergeChainedTxType, migrateWalletRepository, onchainRail, openDatabase, requiresMigration, resolveSendAmount, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, tryResolveSendAmount, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
20557
|
-
//# sourceMappingURL=chunk-
|
|
20558
|
-
//# sourceMappingURL=chunk-
|
|
20922
|
+
export { ARKADE_MAGIC, ActivityRegistry, AmbiguousRouteError, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP21, BIP21Error, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorIdentity, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EmulatorPacket, EsploraProvider, Estimator, Extension, ExtensionNotFoundError, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, PaymentRouter, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, RestEmulatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, UnilateralExit, UnknownPacket, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, arkRail, arkTarget, arkade_exports, assertFinalCommitmentMatchesValidated, assertIntentIdUnique, assertSendableAmount, assertSubmittedArkTxid, assetMintResolver, boardingResolver, btcTarget, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, collabExitResolver, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createAssetPacket, createDefaultActivityRegistry, createDefaultPaymentRouter, createExitChainResolver, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, hasCandidates, intentMatchesFilter, intentPageBounds, invoiceTarget, isArkContract, isBatchSignable, isBtcAddress, isCooperativelyMigratable, isDiscoverable, isHDDeterministicSignCapable, isHDWalletCapable, isLightningInvoice, isLnurl, isMessageBusInitializingError, isMessageBusNotInitializedError, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, makeHandle, matchServerCheckpoints, mergeChainedTxType, migrateWalletRepository, onchainRail, openDatabase, requiresMigration, resolveSendAmount, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, tryResolveSendAmount, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
20923
|
+
//# sourceMappingURL=chunk-T22257HW.js.map
|
|
20924
|
+
//# sourceMappingURL=chunk-T22257HW.js.map
|