@arkade-os/sdk 0.4.47 → 0.4.48-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/expo.cjs +4 -4
- package/dist/adapters/expo.js +2 -2
- package/dist/adapters/indexedDB.cjs +3 -3
- package/dist/adapters/indexedDB.js +2 -2
- package/dist/{asyncStorageTaskQueue-Dowyo59a.d.cts → asyncStorageTaskQueue-CwknfM_j.d.cts} +2 -2
- package/dist/{asyncStorageTaskQueue-Z3aFoXCl.d.ts → asyncStorageTaskQueue-D2Zl7yAB.d.ts} +2 -2
- package/dist/{chunk-JAYOXOLT.cjs → chunk-3HUZAIKI.cjs} +11 -11
- package/dist/{chunk-JAYOXOLT.cjs.map → chunk-3HUZAIKI.cjs.map} +1 -1
- package/dist/{chunk-3N5I6GT6.js → chunk-4AIHKC65.js} +3 -3
- package/dist/{chunk-3N5I6GT6.js.map → chunk-4AIHKC65.js.map} +1 -1
- package/dist/{chunk-HHV5FPC6.cjs → chunk-CFQO5MCM.cjs} +3 -3
- package/dist/chunk-CFQO5MCM.cjs.map +1 -0
- package/dist/{chunk-VE67GMGM.cjs → chunk-EA3IWZ4W.cjs} +7 -7
- package/dist/{chunk-VE67GMGM.cjs.map → chunk-EA3IWZ4W.cjs.map} +1 -1
- package/dist/{chunk-CDDWXBEM.js → chunk-GM6JRQP5.js} +3 -3
- package/dist/chunk-GM6JRQP5.js.map +1 -0
- package/dist/{chunk-WTTLIFS7.cjs → chunk-RJMFTTRJ.cjs} +486 -108
- package/dist/chunk-RJMFTTRJ.cjs.map +1 -0
- package/dist/{chunk-OCS5S3L3.js → chunk-SV4PCGKM.js} +383 -7
- package/dist/chunk-SV4PCGKM.js.map +1 -0
- package/dist/{chunk-AJQ4AOT3.js → chunk-ZRY2KSK5.js} +3 -3
- package/dist/{chunk-AJQ4AOT3.js.map → chunk-ZRY2KSK5.js.map} +1 -1
- package/dist/index.cjs +154 -146
- package/dist/index.d.cts +39 -6
- package/dist/index.d.ts +39 -6
- package/dist/index.js +2 -2
- package/dist/repositories/realm/index.cjs +17 -17
- package/dist/repositories/realm/index.js +3 -3
- package/dist/repositories/sqlite/index.cjs +16 -16
- package/dist/repositories/sqlite/index.js +3 -3
- package/dist/{taskRunner-Dz-TI4Rb.d.ts → taskRunner-Df8YQpn1.d.ts} +1 -1
- package/dist/{taskRunner-Dz47k0lp.d.cts → taskRunner-RYihSj9E.d.cts} +1 -1
- package/dist/wallet/expo/background.cjs +12 -12
- package/dist/wallet/expo/background.d.cts +2 -2
- package/dist/wallet/expo/background.d.ts +2 -2
- package/dist/wallet/expo/background.js +4 -4
- package/dist/wallet/expo/index.cjs +12 -12
- package/dist/wallet/expo/index.d.cts +2 -2
- package/dist/wallet/expo/index.d.ts +2 -2
- package/dist/wallet/expo/index.js +3 -3
- package/dist/{wallet-Oxz_wLxo.d.cts → wallet-B6s7_5bJ.d.cts} +124 -1
- package/dist/{wallet-x7egmXq6.d.ts → wallet-C61huH8i.d.ts} +124 -1
- package/dist/worker/expo/index.cjs +7 -7
- package/dist/worker/expo/index.d.cts +3 -3
- package/dist/worker/expo/index.d.ts +3 -3
- package/dist/worker/expo/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-CDDWXBEM.js.map +0 -1
- package/dist/chunk-HHV5FPC6.cjs.map +0 -1
- package/dist/chunk-OCS5S3L3.js.map +0 -1
- package/dist/chunk-WTTLIFS7.cjs.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Transaction, setArkPsbtField, PrevArkTxField, ConditionWitness, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, craftToSpendTx, getArkPsbtFields, CosignerPublicKey, BufferReader, BufferWriter, OP_RETURN_EMPTY_PKSCRIPT, VtxoTaprootTree, baseFetch, Intent, maybeArkError, isArkError, ArkErrorName, ProviderUnavailableError, FetchError, isFetchTimeoutError, AssetRef, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError } 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, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey,
|
|
1
|
+
import { Transaction, setArkPsbtField, PrevArkTxField, ConditionWitness, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, craftToSpendTx, getArkPsbtFields, CosignerPublicKey, BufferReader, BufferWriter, OP_RETURN_EMPTY_PKSCRIPT, VtxoTaprootTree, baseFetch, Intent, maybeArkError, isArkError, ArkErrorName, ProviderUnavailableError, FetchError, isFetchTimeoutError, AssetRef, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError } from './chunk-GM6JRQP5.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, DefaultVtxo, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, BoardingContractHandler } from './chunk-XN3554FT.js';
|
|
3
3
|
import { VtxoScript, CSVMultisigTapscript, DEFAULT_NETWORK, ArkAddress, sequenceToTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, timelockToSequence, DEFAULT_NETWORK_NAME, getSequence, getNetwork, MultisigTapscript, networks as networks$1, DEFAULT_ARKADE_SERVER_URL } from './chunk-C7TXXTMS.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';
|
|
7
|
-
import { hex, base58, base64 } from '@scure/base';
|
|
7
|
+
import { hex, base58, base64, bech32m } from '@scure/base';
|
|
8
8
|
import * as musig2 from '@scure/btc-signer/musig2.js';
|
|
9
9
|
import { equalBytes as equalBytes$1, bytesToNumberBE } from '@noble/curves/utils.js';
|
|
10
10
|
import { signAsync, schnorr as schnorr$1, Point } from '@noble/secp256k1';
|
|
@@ -2437,6 +2437,15 @@ async function submitOffchainTx(provider, offchainTx, signer, hooks) {
|
|
|
2437
2437
|
await hooks?.afterFinalize?.();
|
|
2438
2438
|
return { arkTxid, signedCheckpointTxs };
|
|
2439
2439
|
}
|
|
2440
|
+
async function signAndSubmitOffchainTx(params) {
|
|
2441
|
+
const offchainTx = buildOffchainTx(params.inputs, params.outputs, params.serverUnrollScript);
|
|
2442
|
+
const signer = {
|
|
2443
|
+
signArkTx: async (arkTx) => ({ arkTx: await params.identity.sign(arkTx) }),
|
|
2444
|
+
signCheckpoint: (checkpoint) => params.identity.sign(checkpoint)
|
|
2445
|
+
};
|
|
2446
|
+
const { arkTxid } = await submitOffchainTx(params.provider, offchainTx, signer);
|
|
2447
|
+
return arkTxid;
|
|
2448
|
+
}
|
|
2440
2449
|
var AmountVariableName = "amount";
|
|
2441
2450
|
var ExpiryVariableName = "expiry";
|
|
2442
2451
|
var BirthVariableName = "birth";
|
|
@@ -2744,6 +2753,7 @@ async function runWithCrossInstanceLock(name, fn) {
|
|
|
2744
2753
|
});
|
|
2745
2754
|
}
|
|
2746
2755
|
var MAX_VTXOS_PER_SETTLEMENT = 50;
|
|
2756
|
+
var MAX_INPUTS_PER_INTENT = 20;
|
|
2747
2757
|
function byValueDescending(vtxos) {
|
|
2748
2758
|
return [...vtxos].sort((a, b) => b.value - a.value);
|
|
2749
2759
|
}
|
|
@@ -4333,6 +4343,96 @@ function readUInt32BE(array, offset) {
|
|
|
4333
4343
|
function noteTapscript(preimageHash) {
|
|
4334
4344
|
return Script.encode(["SHA256", preimageHash, "EQUAL"]);
|
|
4335
4345
|
}
|
|
4346
|
+
var ArkCash = class _ArkCash {
|
|
4347
|
+
constructor(privateKey, serverPubKey, csvTimelock, hrp = _ArkCash.DefaultHRP) {
|
|
4348
|
+
this.csvTimelock = csvTimelock;
|
|
4349
|
+
this.hrp = hrp;
|
|
4350
|
+
if (privateKey.length !== 32) {
|
|
4351
|
+
throw new Error(
|
|
4352
|
+
`Invalid private key length: expected 32 bytes, got ${privateKey.length}`
|
|
4353
|
+
);
|
|
4354
|
+
}
|
|
4355
|
+
if (serverPubKey.length !== 32) {
|
|
4356
|
+
throw new Error(
|
|
4357
|
+
`Invalid server public key length: expected 32 bytes, got ${serverPubKey.length}`
|
|
4358
|
+
);
|
|
4359
|
+
}
|
|
4360
|
+
this._privateKey = privateKey.slice();
|
|
4361
|
+
this._serverPubKey = serverPubKey.slice();
|
|
4362
|
+
this._publicKey = pubSchnorr(this._privateKey);
|
|
4363
|
+
}
|
|
4364
|
+
csvTimelock;
|
|
4365
|
+
hrp;
|
|
4366
|
+
static DefaultHRP = "arkcash";
|
|
4367
|
+
static Version = 0;
|
|
4368
|
+
static PayloadLength = 1 + 32 + 32 + 4;
|
|
4369
|
+
// 69 bytes
|
|
4370
|
+
// Keys are held as private copies so a caller mutating the array it passed
|
|
4371
|
+
// in — or one it reads back from a getter — cannot alter this note's
|
|
4372
|
+
// identity or the outputs derived from it.
|
|
4373
|
+
_privateKey;
|
|
4374
|
+
_serverPubKey;
|
|
4375
|
+
_publicKey;
|
|
4376
|
+
/** The note's private key. Returns a fresh copy; mutating it is a no-op. */
|
|
4377
|
+
get privateKey() {
|
|
4378
|
+
return this._privateKey.slice();
|
|
4379
|
+
}
|
|
4380
|
+
/** The server's public key. Returns a fresh copy; mutating it is a no-op. */
|
|
4381
|
+
get serverPubKey() {
|
|
4382
|
+
return this._serverPubKey.slice();
|
|
4383
|
+
}
|
|
4384
|
+
/** The note's public key. Returns a fresh copy; mutating it is a no-op. */
|
|
4385
|
+
get publicKey() {
|
|
4386
|
+
return this._publicKey.slice();
|
|
4387
|
+
}
|
|
4388
|
+
static generate(serverPubKey, csvTimelock, hrp) {
|
|
4389
|
+
return new _ArkCash(randomPrivateKeyBytes(), serverPubKey, csvTimelock, hrp);
|
|
4390
|
+
}
|
|
4391
|
+
static fromString(encoded) {
|
|
4392
|
+
const decoded = bech32m.decodeUnsafe(encoded.trim().toLowerCase(), 1023);
|
|
4393
|
+
if (!decoded) {
|
|
4394
|
+
throw new Error("Invalid arkcash string: failed to decode bech32m");
|
|
4395
|
+
}
|
|
4396
|
+
const data = new Uint8Array(bech32m.fromWords(decoded.words));
|
|
4397
|
+
if (data.length !== _ArkCash.PayloadLength) {
|
|
4398
|
+
throw new Error(
|
|
4399
|
+
`Invalid arkcash data length: expected ${_ArkCash.PayloadLength} bytes, got ${data.length}`
|
|
4400
|
+
);
|
|
4401
|
+
}
|
|
4402
|
+
const version = data[0];
|
|
4403
|
+
if (version !== _ArkCash.Version) {
|
|
4404
|
+
throw new Error(`Unsupported arkcash version: ${version}`);
|
|
4405
|
+
}
|
|
4406
|
+
const privateKey = data.slice(1, 33);
|
|
4407
|
+
const serverPubKey = data.slice(33, 65);
|
|
4408
|
+
const sequence = new DataView(data.buffer, data.byteOffset + 65, 4).getUint32(0, false);
|
|
4409
|
+
const csvTimelock = sequenceToTimelock(sequence);
|
|
4410
|
+
return new _ArkCash(privateKey, serverPubKey, csvTimelock, decoded.prefix);
|
|
4411
|
+
}
|
|
4412
|
+
toString() {
|
|
4413
|
+
const data = new Uint8Array(_ArkCash.PayloadLength);
|
|
4414
|
+
data[0] = _ArkCash.Version;
|
|
4415
|
+
data.set(this._privateKey, 1);
|
|
4416
|
+
data.set(this._serverPubKey, 33);
|
|
4417
|
+
const sequence = timelockToSequence(this.csvTimelock);
|
|
4418
|
+
new DataView(data.buffer, data.byteOffset + 65, 4).setUint32(0, sequence, false);
|
|
4419
|
+
const words = bech32m.toWords(data);
|
|
4420
|
+
return bech32m.encode(this.hrp, words, 1023);
|
|
4421
|
+
}
|
|
4422
|
+
get identity() {
|
|
4423
|
+
return SingleKey.fromPrivateKey(this._privateKey);
|
|
4424
|
+
}
|
|
4425
|
+
get vtxoScript() {
|
|
4426
|
+
return new DefaultVtxo.Script({
|
|
4427
|
+
pubKey: this._publicKey,
|
|
4428
|
+
serverPubKey: this._serverPubKey,
|
|
4429
|
+
csvTimelock: this.csvTimelock
|
|
4430
|
+
});
|
|
4431
|
+
}
|
|
4432
|
+
address(addressHrp) {
|
|
4433
|
+
return this.vtxoScript.address(addressHrp, this._serverPubKey);
|
|
4434
|
+
}
|
|
4435
|
+
};
|
|
4336
4436
|
|
|
4337
4437
|
// src/repositories/intentRepository.ts
|
|
4338
4438
|
var ALL_INTENT_STATES = [
|
|
@@ -10127,6 +10227,24 @@ async function spendableVtxosExcludingLocked(vtxos, intentRepository) {
|
|
|
10127
10227
|
}
|
|
10128
10228
|
return excludeLockedOutpoints(vtxos, locked);
|
|
10129
10229
|
}
|
|
10230
|
+
var cashReport = (vtxo, reason) => ({
|
|
10231
|
+
txid: vtxo.txid,
|
|
10232
|
+
vout: vtxo.vout,
|
|
10233
|
+
value: vtxo.value,
|
|
10234
|
+
reason
|
|
10235
|
+
});
|
|
10236
|
+
var ArkCashCreateError = class extends Error {
|
|
10237
|
+
constructor(cash, cause) {
|
|
10238
|
+
super(
|
|
10239
|
+
`Failed to create ArkCash: send failed after the note may have been submitted. Recover with claimCash using the token on this error's \`cash\` field.`
|
|
10240
|
+
);
|
|
10241
|
+
this.cash = cash;
|
|
10242
|
+
this.cause = cause;
|
|
10243
|
+
this.name = "ArkCashCreateError";
|
|
10244
|
+
}
|
|
10245
|
+
cash;
|
|
10246
|
+
cause;
|
|
10247
|
+
};
|
|
10130
10248
|
var ReadonlyWallet = class _ReadonlyWallet {
|
|
10131
10249
|
constructor(identity, network, onchainProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, dustAmount, walletRepository, contractRepository, delegateProvider, watcherConfig, walletContractTimelocks) {
|
|
10132
10250
|
this.identity = identity;
|
|
@@ -12586,7 +12704,6 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12586
12704
|
if (!hasPending) {
|
|
12587
12705
|
return { finalized: [], pending: [] };
|
|
12588
12706
|
}
|
|
12589
|
-
const MAX_INPUTS_PER_INTENT = 20;
|
|
12590
12707
|
if (!vtxos || vtxos.length === 0) {
|
|
12591
12708
|
const scriptMap = await this.getScriptMap();
|
|
12592
12709
|
const allExtended = [];
|
|
@@ -12696,6 +12813,265 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12696
12813
|
settings: { ...state.settings, hasPendingTx: value }
|
|
12697
12814
|
}));
|
|
12698
12815
|
}
|
|
12816
|
+
/**
|
|
12817
|
+
* Create an ArkCash bearer instrument.
|
|
12818
|
+
*
|
|
12819
|
+
* Generates a fresh keypair, sends the specified amount to a DefaultVtxo
|
|
12820
|
+
* controlled by the new key, and returns the encoded arkcash string.
|
|
12821
|
+
* The receiver can claim the funds using `claimCash()` without ever
|
|
12822
|
+
* sharing their address.
|
|
12823
|
+
*
|
|
12824
|
+
* ArkCash is a short-lived instrument: it carries a private key, so it is
|
|
12825
|
+
* meant to be handed over and claimed promptly, not held. A note left
|
|
12826
|
+
* unclaimed past its batch expiry is swept by the server and `claimCash`
|
|
12827
|
+
* can only report it, not move it.
|
|
12828
|
+
*
|
|
12829
|
+
* @param amount - Amount in satoshis to send. Must be a whole number of
|
|
12830
|
+
* sats at or above the dust threshold — a below-dust amount would mint an
|
|
12831
|
+
* OP_RETURN output that is unspendable as cash.
|
|
12832
|
+
* @returns The encoded arkcash string (e.g., "arkcash1...")
|
|
12833
|
+
*/
|
|
12834
|
+
async createCash(amount) {
|
|
12835
|
+
if (!Number.isSafeInteger(amount) || amount < Number(this.dustAmount)) {
|
|
12836
|
+
throw new Error(
|
|
12837
|
+
`Invalid ArkCash amount ${amount}: must be a whole number of sats >= dust (${this.dustAmount})`
|
|
12838
|
+
);
|
|
12839
|
+
}
|
|
12840
|
+
const cashHrp = this.network.hrp.replace(/ark$/, "arkcash");
|
|
12841
|
+
const cash = ArkCash.generate(
|
|
12842
|
+
this.arkServerPublicKey,
|
|
12843
|
+
this.offchainTapscript.options.csvTimelock,
|
|
12844
|
+
cashHrp
|
|
12845
|
+
);
|
|
12846
|
+
const address = cash.address(this.network.hrp).encode();
|
|
12847
|
+
const cashStr = cash.toString();
|
|
12848
|
+
try {
|
|
12849
|
+
await this.send({ address, amount });
|
|
12850
|
+
} catch (error) {
|
|
12851
|
+
throw new ArkCashCreateError(cashStr, error);
|
|
12852
|
+
}
|
|
12853
|
+
return cashStr;
|
|
12854
|
+
}
|
|
12855
|
+
/**
|
|
12856
|
+
* Claim an ArkCash bearer instrument: sweep what can be swept, report the
|
|
12857
|
+
* rest.
|
|
12858
|
+
*
|
|
12859
|
+
* Every spendable VTXO at the arkcash address is swept to this wallet in
|
|
12860
|
+
* its own offchain transaction, signed with the key carried by the arkcash
|
|
12861
|
+
* string. Nothing is ever persisted: no contract is imported, and the
|
|
12862
|
+
* arkcash key is not stored. Anything that cannot be swept — server-swept,
|
|
12863
|
+
* subdust, already claimed, or asset-bearing — is returned in `unclaimed`
|
|
12864
|
+
* with a per-VTXO reason and otherwise ignored.
|
|
12865
|
+
*
|
|
12866
|
+
* The arkcash string is the recovery token: a claim interrupted between
|
|
12867
|
+
* submit and finalize is completed by simply re-running `claimCash`, which
|
|
12868
|
+
* drains any pending arkcash transaction on the server before sweeping.
|
|
12869
|
+
*
|
|
12870
|
+
* @param cashStr - The encoded arkcash string (e.g., "arkcash1...")
|
|
12871
|
+
* @returns The swept total and the report of what was left behind. The
|
|
12872
|
+
* shape is open: further buckets may be added alongside `unclaimed`.
|
|
12873
|
+
*/
|
|
12874
|
+
async claimCash(cashStr) {
|
|
12875
|
+
const cash = ArkCash.fromString(cashStr);
|
|
12876
|
+
const cashScript = cash.vtxoScript;
|
|
12877
|
+
const cashPkScript = hex.encode(cashScript.pkScript);
|
|
12878
|
+
const scripts = [cashPkScript];
|
|
12879
|
+
let vtxos = await this.fetchAllVtxos(scripts);
|
|
12880
|
+
if (vtxos.length === 0) {
|
|
12881
|
+
throw new Error("No VTXOs found for this arkcash");
|
|
12882
|
+
}
|
|
12883
|
+
const myPkScript = ArkAddress.decode(await this.getAddress()).pkScript;
|
|
12884
|
+
let { spendable, unclaimed } = this.classifyCashVtxos(vtxos);
|
|
12885
|
+
let swept = 0;
|
|
12886
|
+
const drainable = vtxos.filter((vtxo) => !isSubdust(vtxo, this.dustAmount));
|
|
12887
|
+
if (drainable.length > 0) {
|
|
12888
|
+
let drained = { count: 0, swept: 0, claimed: /* @__PURE__ */ new Set() };
|
|
12889
|
+
try {
|
|
12890
|
+
drained = await this.finalizePendingCashTxs(
|
|
12891
|
+
cash,
|
|
12892
|
+
drainable,
|
|
12893
|
+
cashScript,
|
|
12894
|
+
myPkScript
|
|
12895
|
+
);
|
|
12896
|
+
} catch (error) {
|
|
12897
|
+
console.error("Failed to drain pending arkcash txs:", error);
|
|
12898
|
+
}
|
|
12899
|
+
if (drained.count > 0) {
|
|
12900
|
+
vtxos = await this.fetchAllVtxos(scripts);
|
|
12901
|
+
({ spendable, unclaimed } = this.classifyCashVtxos(vtxos));
|
|
12902
|
+
swept += drained.swept;
|
|
12903
|
+
unclaimed = unclaimed.filter(
|
|
12904
|
+
(vtxo) => !drained.claimed.has(`${vtxo.txid}:${vtxo.vout}`)
|
|
12905
|
+
);
|
|
12906
|
+
}
|
|
12907
|
+
}
|
|
12908
|
+
if (spendable.length > 0) {
|
|
12909
|
+
const info = await this.arkProvider.getInfo();
|
|
12910
|
+
const serverUnrollScript = CSVMultisigTapscript.decode(
|
|
12911
|
+
hex.decode(info.checkpointTapscript)
|
|
12912
|
+
);
|
|
12913
|
+
for (const vtxo of spendable) {
|
|
12914
|
+
try {
|
|
12915
|
+
await signAndSubmitOffchainTx({
|
|
12916
|
+
identity: cash.identity,
|
|
12917
|
+
provider: this.arkProvider,
|
|
12918
|
+
inputs: [
|
|
12919
|
+
{
|
|
12920
|
+
txid: vtxo.txid,
|
|
12921
|
+
vout: vtxo.vout,
|
|
12922
|
+
value: vtxo.value,
|
|
12923
|
+
tapLeafScript: cashScript.forfeit(),
|
|
12924
|
+
tapTree: cashScript.encode()
|
|
12925
|
+
}
|
|
12926
|
+
],
|
|
12927
|
+
outputs: [{ script: myPkScript, amount: BigInt(vtxo.value) }],
|
|
12928
|
+
serverUnrollScript
|
|
12929
|
+
});
|
|
12930
|
+
swept += vtxo.value;
|
|
12931
|
+
} catch (error) {
|
|
12932
|
+
console.error(`Failed to sweep arkcash VTXO ${vtxo.txid}:${vtxo.vout}:`, error);
|
|
12933
|
+
unclaimed.push(cashReport(vtxo, "sweep-failed"));
|
|
12934
|
+
}
|
|
12935
|
+
}
|
|
12936
|
+
}
|
|
12937
|
+
return {
|
|
12938
|
+
swept,
|
|
12939
|
+
unclaimed: {
|
|
12940
|
+
amount: unclaimed.reduce((total, vtxo) => total + vtxo.value, 0),
|
|
12941
|
+
vtxos: unclaimed
|
|
12942
|
+
}
|
|
12943
|
+
};
|
|
12944
|
+
}
|
|
12945
|
+
/**
|
|
12946
|
+
* Split the VTXOs at an arkcash address into the ones the thin sweep can
|
|
12947
|
+
* move and the ones it can only report.
|
|
12948
|
+
*/
|
|
12949
|
+
classifyCashVtxos(vtxos) {
|
|
12950
|
+
const spendable = [];
|
|
12951
|
+
const unclaimed = [];
|
|
12952
|
+
for (const vtxo of vtxos) {
|
|
12953
|
+
if (!isSpendable(vtxo)) {
|
|
12954
|
+
unclaimed.push(cashReport(vtxo, "already-spent"));
|
|
12955
|
+
} else if (isSubdust(vtxo, this.dustAmount)) {
|
|
12956
|
+
unclaimed.push(cashReport(vtxo, "subdust"));
|
|
12957
|
+
} else if (isRecoverable(vtxo)) {
|
|
12958
|
+
unclaimed.push(cashReport(vtxo, "swept"));
|
|
12959
|
+
} else if (vtxo.assets && vtxo.assets.length > 0) {
|
|
12960
|
+
unclaimed.push(cashReport(vtxo, "has-assets"));
|
|
12961
|
+
} else {
|
|
12962
|
+
spendable.push(vtxo);
|
|
12963
|
+
}
|
|
12964
|
+
}
|
|
12965
|
+
return { spendable, unclaimed };
|
|
12966
|
+
}
|
|
12967
|
+
/** Read every page of an unfiltered VTXO query for the given scripts. */
|
|
12968
|
+
async fetchAllVtxos(scripts) {
|
|
12969
|
+
const pageSize = 100;
|
|
12970
|
+
const all = [];
|
|
12971
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12972
|
+
for (let pageIndex = 0; ; pageIndex++) {
|
|
12973
|
+
const { vtxos, page } = await this.indexerProvider.getVtxos({
|
|
12974
|
+
scripts,
|
|
12975
|
+
pageIndex,
|
|
12976
|
+
pageSize
|
|
12977
|
+
});
|
|
12978
|
+
for (const vtxo of vtxos) {
|
|
12979
|
+
const outpoint = `${vtxo.txid}:${vtxo.vout}`;
|
|
12980
|
+
if (seen.has(outpoint)) continue;
|
|
12981
|
+
seen.add(outpoint);
|
|
12982
|
+
all.push(vtxo);
|
|
12983
|
+
}
|
|
12984
|
+
if (!page || vtxos.length < pageSize) return all;
|
|
12985
|
+
}
|
|
12986
|
+
}
|
|
12987
|
+
/**
|
|
12988
|
+
* Complete any sweep a previous `claimCash` registered but never finalized.
|
|
12989
|
+
* A thin variant of {@link finalizePendingTxs}, scoped to the arkcash key:
|
|
12990
|
+
* the intent is signed with it, and so are the returned checkpoints.
|
|
12991
|
+
*
|
|
12992
|
+
* A drained sweep is not automatically *ours*. Whoever registered it chose
|
|
12993
|
+
* the destination, so a tx a different claimer left half-finished pays that
|
|
12994
|
+
* claimer — finalizing it is still right (the input is spent either way, and
|
|
12995
|
+
* completing it unsticks the funds), but only the value it actually pays to
|
|
12996
|
+
* `myPkScript` may be counted as claimed here.
|
|
12997
|
+
*
|
|
12998
|
+
* @param vtxos - VTXOs at the arkcash contract's own pkScript, spent ones
|
|
12999
|
+
* included (a registered sweep marks its input spent). Any other outpoint —
|
|
13000
|
+
* subdust above all — would make the proof invalid, since it describes every
|
|
13001
|
+
* input by that pkScript.
|
|
13002
|
+
* @returns The number of pending txs finalized, the sats among them paid to
|
|
13003
|
+
* this wallet, and the outpoints those txs consumed to pay it.
|
|
13004
|
+
*/
|
|
13005
|
+
async finalizePendingCashTxs(cash, vtxos, cashScript, myPkScript) {
|
|
13006
|
+
const result = { count: 0, swept: 0, claimed: /* @__PURE__ */ new Set() };
|
|
13007
|
+
const inputs = vtxos.map((vtxo) => ({
|
|
13008
|
+
...vtxo,
|
|
13009
|
+
forfeitTapLeafScript: cashScript.forfeit(),
|
|
13010
|
+
intentTapLeafScript: cashScript.forfeit(),
|
|
13011
|
+
tapTree: cashScript.encode()
|
|
13012
|
+
}));
|
|
13013
|
+
if (inputs.length === 0) return result;
|
|
13014
|
+
const identity = cash.identity;
|
|
13015
|
+
const seenTxids = /* @__PURE__ */ new Set();
|
|
13016
|
+
const pendingTxs = [];
|
|
13017
|
+
for (let i = 0; i < inputs.length; i += MAX_INPUTS_PER_INTENT) {
|
|
13018
|
+
const batch = inputs.slice(i, i + MAX_INPUTS_PER_INTENT);
|
|
13019
|
+
const message = { type: "get-pending-tx", expire_at: 0 };
|
|
13020
|
+
const proof = Intent.create(message, batch, []);
|
|
13021
|
+
const signedProof = await identity.sign(
|
|
13022
|
+
proof,
|
|
13023
|
+
Array.from({ length: batch.length + 1 }, (_, j) => j)
|
|
13024
|
+
);
|
|
13025
|
+
const batchPending = await this.arkProvider.getPendingTxs({
|
|
13026
|
+
proof: base64.encode(signedProof.toPSBT()),
|
|
13027
|
+
message
|
|
13028
|
+
});
|
|
13029
|
+
for (const pendingTx of batchPending) {
|
|
13030
|
+
if (seenTxids.has(pendingTx.arkTxid)) continue;
|
|
13031
|
+
seenTxids.add(pendingTx.arkTxid);
|
|
13032
|
+
pendingTxs.push(pendingTx);
|
|
13033
|
+
}
|
|
13034
|
+
}
|
|
13035
|
+
const myPkScriptHex = hex.encode(myPkScript);
|
|
13036
|
+
for (const pendingTx of pendingTxs) {
|
|
13037
|
+
try {
|
|
13038
|
+
const checkpointTxs = pendingTx.signedCheckpointTxs.map(
|
|
13039
|
+
(checkpoint) => Transaction$2.fromPSBT(base64.decode(checkpoint))
|
|
13040
|
+
);
|
|
13041
|
+
const finalCheckpoints = await Promise.all(
|
|
13042
|
+
checkpointTxs.map(
|
|
13043
|
+
async (checkpoint) => base64.encode((await identity.sign(checkpoint)).toPSBT())
|
|
13044
|
+
)
|
|
13045
|
+
);
|
|
13046
|
+
await this.arkProvider.finalizeTx(pendingTx.arkTxid, finalCheckpoints);
|
|
13047
|
+
result.count++;
|
|
13048
|
+
const paidToMe = this.arkTxAmountPaidTo(pendingTx.finalArkTx, myPkScriptHex);
|
|
13049
|
+
if (paidToMe === 0) continue;
|
|
13050
|
+
result.swept += paidToMe;
|
|
13051
|
+
for (const checkpoint of checkpointTxs) {
|
|
13052
|
+
for (let i = 0; i < checkpoint.inputsLength; i++) {
|
|
13053
|
+
const input = checkpoint.getInput(i);
|
|
13054
|
+
if (!input.txid) continue;
|
|
13055
|
+
result.claimed.add(`${hex.encode(input.txid)}:${input.index}`);
|
|
13056
|
+
}
|
|
13057
|
+
}
|
|
13058
|
+
} catch (error) {
|
|
13059
|
+
console.error(`Failed to finalize pending arkcash tx ${pendingTx.arkTxid}:`, error);
|
|
13060
|
+
}
|
|
13061
|
+
}
|
|
13062
|
+
return result;
|
|
13063
|
+
}
|
|
13064
|
+
/** Sum the outputs of an ark tx PSBT that pay the given scriptPubKey. */
|
|
13065
|
+
arkTxAmountPaidTo(arkTxPsbt, pkScriptHex) {
|
|
13066
|
+
const arkTx = Transaction$2.fromPSBT(base64.decode(arkTxPsbt));
|
|
13067
|
+
let total = 0;
|
|
13068
|
+
for (let i = 0; i < arkTx.outputsLength; i++) {
|
|
13069
|
+
const output = arkTx.getOutput(i);
|
|
13070
|
+
if (!output.script || output.amount === void 0) continue;
|
|
13071
|
+
if (hex.encode(output.script) === pkScriptHex) total += Number(output.amount);
|
|
13072
|
+
}
|
|
13073
|
+
return total;
|
|
13074
|
+
}
|
|
12699
13075
|
/**
|
|
12700
13076
|
* Send BTC and/or assets to one or more recipients.
|
|
12701
13077
|
*
|
|
@@ -19412,6 +19788,6 @@ function isArkContract(str) {
|
|
|
19412
19788
|
return str.startsWith(ARKCONTRACT_PREFIX + "=");
|
|
19413
19789
|
}
|
|
19414
19790
|
|
|
19415
|
-
export { ARKADE_MAGIC, ActivityRegistry, ArkNote, AssetManager, 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, 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, arkade_exports, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createAssetPacket, createDefaultActivityRegistry, createExitChainResolver, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isExpired, isRecoverable, isRetryableProviderError, isSpendable, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
19416
|
-
//# sourceMappingURL=chunk-
|
|
19417
|
-
//# sourceMappingURL=chunk-
|
|
19791
|
+
export { ARKADE_MAGIC, ActivityRegistry, ArkCash, ArkCashCreateError, ArkNote, AssetManager, 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, 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, arkade_exports, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createAssetPacket, createDefaultActivityRegistry, createExitChainResolver, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isExpired, isRecoverable, isRetryableProviderError, isSpendable, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
19792
|
+
//# sourceMappingURL=chunk-SV4PCGKM.js.map
|
|
19793
|
+
//# sourceMappingURL=chunk-SV4PCGKM.js.map
|