@chironbuilder/ootle-sdk 0.1.3 → 0.1.4
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/wallet.d.ts +47 -0
- package/dist/wallet.d.ts.map +1 -1
- package/dist/wallet.js +146 -1
- package/package.json +1 -1
package/dist/wallet.d.ts
CHANGED
|
@@ -418,6 +418,53 @@ export declare class OotleAccount implements WalletAccountApi {
|
|
|
418
418
|
redeemStealthOutputAndExecute(resourceAddress: string, commitmentHex: string, revealedAmount: bigint, followUpInstructions: Instruction[], relatedComponents?: string[], maxFee?: bigint): Promise<{
|
|
419
419
|
transactionId: string;
|
|
420
420
|
}>;
|
|
421
|
+
/**
|
|
422
|
+
* Like `redeemStealthOutputAndExecute`, but pays the transaction fee from a **second stealth
|
|
423
|
+
* UTXO** instead of this account's revealed balance — so the transaction never touches, and
|
|
424
|
+
* never reveals, this account's on-chain address at all. Confirmed live: the resulting
|
|
425
|
+
* transaction's `up_substates`/`down_substates` contain only the two stealth UTXOs, the
|
|
426
|
+
* redeemed resource, and whatever `relatedComponents` touch — no `component_...` belonging to
|
|
427
|
+
* this account appears anywhere in it.
|
|
428
|
+
*
|
|
429
|
+
* Required whenever the follow-up call itself carries information that would deanonymize the
|
|
430
|
+
* account if the fee input did (e.g. a voting ballot's ranking): a revealed fee input signs
|
|
431
|
+
* with this account's ordinary key, which links the transaction to the account exactly as
|
|
432
|
+
* plainly as if the whole thing were sent unshielded — see the confidential-rcv-template
|
|
433
|
+
* README's "Fee-from-stealth requirement (MUST)" for the canonical explanation.
|
|
434
|
+
*
|
|
435
|
+
* Both stealth inputs are spent via the same mechanism `redeemStealthOutputAndExecute` uses
|
|
436
|
+
* (KeyPath one-time-key ownership, resolved by decrypting each UTXO with this account's own
|
|
437
|
+
* view secret) — this method just does it twice, for two independent `StealthTransfer`
|
|
438
|
+
* instructions in the same transaction: the redeemed resource's spend carries the follow-up
|
|
439
|
+
* call (main instructions), the fee resource's spend carries `PayFeeFromBucket` (fee
|
|
440
|
+
* instructions, its own separate workspace scope — same convention as `followUpInstructions`,
|
|
441
|
+
* claims workspace id `0` there too).
|
|
442
|
+
*
|
|
443
|
+
* Neither stealth input's one-time key seals the transaction in the sense the protocol's
|
|
444
|
+
* `stealth_seal_with` API suggests one must — empirically (and consistent with how every other
|
|
445
|
+
* stealth-spending method in this file already works), the network accepts a transaction sealed
|
|
446
|
+
* by an arbitrary throwaway keypair as long as every stealth input's one-time-key authorization
|
|
447
|
+
* is signed with respect to that same seal key; `signTransaction` generates one automatically.
|
|
448
|
+
* Deliberately **omits** this account's own ordinary signature entirely (unlike every other
|
|
449
|
+
* stealth-spending method here, which signs with `mustSignWithAccountKey: true` by default) —
|
|
450
|
+
* adding it would attach the account's ordinary public key to the transaction, defeating the
|
|
451
|
+
* entire point of a stealth-funded fee.
|
|
452
|
+
*
|
|
453
|
+
* @param feeResourceAddress The fee-currency resource (almost always XTR/TARI).
|
|
454
|
+
* @param feeCommitmentHex A stealth UTXO of `feeResourceAddress` this account owns, with
|
|
455
|
+
* enough value to cover `maxFee` — e.g. produced by this account's own `shield()` call
|
|
456
|
+
* against `feeResourceAddress`. Consumed in full; the remainder above `maxFee` becomes a new
|
|
457
|
+
* stealth change output back to this account.
|
|
458
|
+
* @returns `feeChangeCommitment` — the new stealth UTXO holding the fee input's unspent
|
|
459
|
+
* remainder. There is no way to discover it other than being told, same as any other stealth
|
|
460
|
+
* output belonging to this account that wasn't created by this account's own `shield()`
|
|
461
|
+
* (which records its own outputs locally) — callers doing several of these in sequence must
|
|
462
|
+
* thread this value into the next call's `feeCommitmentHex` themselves.
|
|
463
|
+
*/
|
|
464
|
+
redeemStealthOutputWithPrivateFee(resourceAddress: string, commitmentHex: string, revealedAmount: bigint, followUpInstructions: Instruction[], feeResourceAddress: string, feeCommitmentHex: string, maxFee: bigint, relatedComponents?: string[]): Promise<{
|
|
465
|
+
transactionId: string;
|
|
466
|
+
feeChangeCommitment: string;
|
|
467
|
+
}>;
|
|
421
468
|
/**
|
|
422
469
|
* Funds an HTLC (hashed timelock contract): creates a stealth output for `amount` of
|
|
423
470
|
* `resourceAddress`, gated not by a normal one-time stealth key but by a two-leaf TIP-0006
|
package/dist/wallet.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,
|
|
1
|
+
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"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"}
|
package/dist/wallet.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mask, OotleWallet, StealthInput, StealthInputsStatement, StealthOutputsStatement, StealthTransfer, StealthTransferStatement, TransactionBuilder, WalletStealthAuthorizer, WasmStealthCrypto, XTR_FAUCET_CLAIM_RESOURCE_ADDRESS, XTR_FAUCET_COMPONENT_ADDRESS, XTR_FAUCET_VAULT_ADDRESS, amountLiteral, createOutput, decryptOwnedUtxo, defaultIndexerUrl, getVaultIdsForAccount, resolveMaxEpoch, resolveTransaction, resourceAddressLiteral, sealTransaction, sendTransaction, signTransaction, stealthUtxoSubstateId, submitTransaction, } from "@tari-project/ootle";
|
|
1
|
+
import { Mask, OotleWallet, StealthInput, StealthInputsStatement, StealthOutputsStatement, StealthTransfer, StealthTransferStatement, TransactionBuilder, WalletStealthAuthorizer, WasmStealthCrypto, XTR_FAUCET_CLAIM_RESOURCE_ADDRESS, XTR_FAUCET_COMPONENT_ADDRESS, XTR_FAUCET_VAULT_ADDRESS, amountLiteral, createOutput, decryptOwnedUtxo, defaultIndexerUrl, getVaultIdsForAccount, resolveMaxEpoch, resolveTransaction, resourceAddressLiteral, sealTransaction, sendTransaction, serializeUnsignedTx, signTransaction, stealthUtxoSubstateId, submitTransaction, } from "@tari-project/ootle";
|
|
2
2
|
import { IndexerProvider } from "@tari-project/ootle-indexer";
|
|
3
3
|
import { SecretKeyWallet } from "@tari-project/ootle-secret-key-wallet";
|
|
4
4
|
import { buildScriptPathWitness, buildStealthTransferStatement, createConfidentialWithdrawProofLiteral, createStealthOutputWitness, parseOotleAddress, publicKeyFromSecretKey, schnorrSign, stealthDhSecret, validateStealthTransfer, } from "@tari-project/ootle-wasm";
|
|
@@ -1098,6 +1098,151 @@ export class OotleAccount {
|
|
|
1098
1098
|
await recordKnownVersions(response);
|
|
1099
1099
|
return { transactionId };
|
|
1100
1100
|
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Like `redeemStealthOutputAndExecute`, but pays the transaction fee from a **second stealth
|
|
1103
|
+
* UTXO** instead of this account's revealed balance — so the transaction never touches, and
|
|
1104
|
+
* never reveals, this account's on-chain address at all. Confirmed live: the resulting
|
|
1105
|
+
* transaction's `up_substates`/`down_substates` contain only the two stealth UTXOs, the
|
|
1106
|
+
* redeemed resource, and whatever `relatedComponents` touch — no `component_...` belonging to
|
|
1107
|
+
* this account appears anywhere in it.
|
|
1108
|
+
*
|
|
1109
|
+
* Required whenever the follow-up call itself carries information that would deanonymize the
|
|
1110
|
+
* account if the fee input did (e.g. a voting ballot's ranking): a revealed fee input signs
|
|
1111
|
+
* with this account's ordinary key, which links the transaction to the account exactly as
|
|
1112
|
+
* plainly as if the whole thing were sent unshielded — see the confidential-rcv-template
|
|
1113
|
+
* README's "Fee-from-stealth requirement (MUST)" for the canonical explanation.
|
|
1114
|
+
*
|
|
1115
|
+
* Both stealth inputs are spent via the same mechanism `redeemStealthOutputAndExecute` uses
|
|
1116
|
+
* (KeyPath one-time-key ownership, resolved by decrypting each UTXO with this account's own
|
|
1117
|
+
* view secret) — this method just does it twice, for two independent `StealthTransfer`
|
|
1118
|
+
* instructions in the same transaction: the redeemed resource's spend carries the follow-up
|
|
1119
|
+
* call (main instructions), the fee resource's spend carries `PayFeeFromBucket` (fee
|
|
1120
|
+
* instructions, its own separate workspace scope — same convention as `followUpInstructions`,
|
|
1121
|
+
* claims workspace id `0` there too).
|
|
1122
|
+
*
|
|
1123
|
+
* Neither stealth input's one-time key seals the transaction in the sense the protocol's
|
|
1124
|
+
* `stealth_seal_with` API suggests one must — empirically (and consistent with how every other
|
|
1125
|
+
* stealth-spending method in this file already works), the network accepts a transaction sealed
|
|
1126
|
+
* by an arbitrary throwaway keypair as long as every stealth input's one-time-key authorization
|
|
1127
|
+
* is signed with respect to that same seal key; `signTransaction` generates one automatically.
|
|
1128
|
+
* Deliberately **omits** this account's own ordinary signature entirely (unlike every other
|
|
1129
|
+
* stealth-spending method here, which signs with `mustSignWithAccountKey: true` by default) —
|
|
1130
|
+
* adding it would attach the account's ordinary public key to the transaction, defeating the
|
|
1131
|
+
* entire point of a stealth-funded fee.
|
|
1132
|
+
*
|
|
1133
|
+
* @param feeResourceAddress The fee-currency resource (almost always XTR/TARI).
|
|
1134
|
+
* @param feeCommitmentHex A stealth UTXO of `feeResourceAddress` this account owns, with
|
|
1135
|
+
* enough value to cover `maxFee` — e.g. produced by this account's own `shield()` call
|
|
1136
|
+
* against `feeResourceAddress`. Consumed in full; the remainder above `maxFee` becomes a new
|
|
1137
|
+
* stealth change output back to this account.
|
|
1138
|
+
* @returns `feeChangeCommitment` — the new stealth UTXO holding the fee input's unspent
|
|
1139
|
+
* remainder. There is no way to discover it other than being told, same as any other stealth
|
|
1140
|
+
* output belonging to this account that wasn't created by this account's own `shield()`
|
|
1141
|
+
* (which records its own outputs locally) — callers doing several of these in sequence must
|
|
1142
|
+
* thread this value into the next call's `feeCommitmentHex` themselves.
|
|
1143
|
+
*/
|
|
1144
|
+
async redeemStealthOutputWithPrivateFee(resourceAddress, commitmentHex, revealedAmount, followUpInstructions, feeResourceAddress, feeCommitmentHex, maxFee, relatedComponents = []) {
|
|
1145
|
+
if (revealedAmount <= 0n)
|
|
1146
|
+
throw new Error(`redeemStealthOutputWithPrivateFee: revealedAmount must be > 0, got ${revealedAmount}`);
|
|
1147
|
+
if (maxFee <= 0n)
|
|
1148
|
+
throw new Error(`redeemStealthOutputWithPrivateFee: maxFee must be > 0, got ${maxFee}`);
|
|
1149
|
+
const provider = await this.getProvider();
|
|
1150
|
+
const crypto = new WasmStealthCrypto(this.network);
|
|
1151
|
+
const walletAddress = await this.getWalletAddress();
|
|
1152
|
+
const viewSecret = await this.signer.getViewSecret();
|
|
1153
|
+
const decryptStealthInput = async (resource, commitmentHexIn) => {
|
|
1154
|
+
const commitment = fromHex(commitmentHexIn);
|
|
1155
|
+
const substateId = stealthUtxoSubstateId(resource, commitment);
|
|
1156
|
+
const substate = await provider.getSubstate(substateId);
|
|
1157
|
+
const decrypted = await decryptOwnedUtxo(crypto, viewSecret, substate, substateId);
|
|
1158
|
+
if (!decrypted) {
|
|
1159
|
+
throw new Error(`redeemStealthOutputWithPrivateFee: cannot decrypt ${substateId} -- it doesn't belong to this account, or is already spent.`);
|
|
1160
|
+
}
|
|
1161
|
+
return { commitmentHex: commitmentHexIn, substateId, mask: decrypted.mask, value: decrypted.value };
|
|
1162
|
+
};
|
|
1163
|
+
const redeemed = await decryptStealthInput(resourceAddress, commitmentHex);
|
|
1164
|
+
const feeInput = await decryptStealthInput(feeResourceAddress, feeCommitmentHex);
|
|
1165
|
+
if (feeInput.value <= maxFee) {
|
|
1166
|
+
throw new Error(`redeemStealthOutputWithPrivateFee: fee UTXO (${feeInput.value}) is too small to cover maxFee (${maxFee})`);
|
|
1167
|
+
}
|
|
1168
|
+
const feeChange = feeInput.value - maxFee;
|
|
1169
|
+
const inputSkeleton = (hex) => JSON.stringify({ inputs: [{ commitment: hex, witness: "KeyPath" }], revealed_amount: "0" });
|
|
1170
|
+
// Redeemed resource: 1 stealth input -> 0 stealth outputs, fully revealed into the bucket
|
|
1171
|
+
// `followUpInstructions` consumes.
|
|
1172
|
+
const redeemedInputsStatement = new StealthInputsStatement([], 0n, inputSkeleton(redeemed.commitmentHex));
|
|
1173
|
+
const redeemedOutputsStatement = new StealthOutputsStatement(JSON.stringify({ outputs: [], revealed_output_amount: revealedAmount.toString(), agg_range_proof: "" }));
|
|
1174
|
+
const redeemedAggInputMask = await crypto.aggregateInputMasks([redeemed.mask]);
|
|
1175
|
+
const redeemedBalanceProof = await crypto.generateBalanceProofSignature(redeemedAggInputMask, Mask.zero(), redeemedInputsStatement.statementJson, redeemedOutputsStatement.statementJson);
|
|
1176
|
+
const redeemedStatement = new StealthTransferStatement(redeemedInputsStatement, redeemedOutputsStatement, redeemedBalanceProof);
|
|
1177
|
+
await crypto.validateTransfer(redeemedStatement);
|
|
1178
|
+
// Fee resource: 1 stealth input -> 1 stealth change output + revealed maxFee.
|
|
1179
|
+
const feeChangeOutput = createOutput({ destination: walletAddress, amount: feeChange, resourceAddress: feeResourceAddress });
|
|
1180
|
+
const { statement: feeOutputsStatement, outputMask: feeOutputMask } = await crypto.generateOutputsStatement([feeChangeOutput], maxFee);
|
|
1181
|
+
const feeInputsStatement = new StealthInputsStatement([], 0n, inputSkeleton(feeInput.commitmentHex));
|
|
1182
|
+
const feeAggInputMask = await crypto.aggregateInputMasks([feeInput.mask]);
|
|
1183
|
+
const feeBalanceProof = await crypto.generateBalanceProofSignature(feeAggInputMask, feeOutputMask, feeInputsStatement.statementJson, feeOutputsStatement.statementJson);
|
|
1184
|
+
const feeStatement = new StealthTransferStatement(feeInputsStatement, feeOutputsStatement, feeBalanceProof);
|
|
1185
|
+
await crypto.validateTransfer(feeStatement);
|
|
1186
|
+
const feeChangeCommitment = feeOutputsStatement.parsed().outputs[0].output.commitment;
|
|
1187
|
+
const maxEpoch = await resolveMaxEpoch(provider);
|
|
1188
|
+
const builder = TransactionBuilder.new(this.network, maxEpoch)
|
|
1189
|
+
.addInstruction({
|
|
1190
|
+
StealthTransfer: {
|
|
1191
|
+
resource_address_ref: { Address: resourceAddress },
|
|
1192
|
+
statement: { __ootleRawJson: redeemedStatement.toCompactJson() },
|
|
1193
|
+
revealed_input_bucket: null,
|
|
1194
|
+
},
|
|
1195
|
+
})
|
|
1196
|
+
.addInstruction({ PutLastInstructionOutputOnWorkspace: { key: 0 } })
|
|
1197
|
+
.withInstructions(followUpInstructions)
|
|
1198
|
+
.addFeeInstruction({
|
|
1199
|
+
StealthTransfer: {
|
|
1200
|
+
resource_address_ref: { Address: feeResourceAddress },
|
|
1201
|
+
statement: { __ootleRawJson: feeStatement.toCompactJson() },
|
|
1202
|
+
revealed_input_bucket: null,
|
|
1203
|
+
},
|
|
1204
|
+
})
|
|
1205
|
+
.addFeeInstruction({ PutLastInstructionOutputOnWorkspace: { key: 0 } })
|
|
1206
|
+
.addFeeInstruction({ PayFeeFromBucket: { bucket: { id: 0, offset: null } } })
|
|
1207
|
+
.addInput({ substate_id: resourceAddress, version: null })
|
|
1208
|
+
.addInput({ substate_id: redeemed.substateId, version: null })
|
|
1209
|
+
.addInput({ substate_id: feeResourceAddress, version: null })
|
|
1210
|
+
.addInput({ substate_id: feeInput.substateId, version: null });
|
|
1211
|
+
for (const component of relatedComponents) {
|
|
1212
|
+
builder.addInput({ substate_id: component, version: null });
|
|
1213
|
+
for (const vaultId of await getVaultIdsForAccount(provider, component)) {
|
|
1214
|
+
builder.addInput({ substate_id: vaultId, version: null });
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
const unsignedTx = await resolveTransaction(provider, builder.buildUnsignedTransaction());
|
|
1218
|
+
// One addStealthSignature per stealth input, bound to a shared (arbitrary) seal key that
|
|
1219
|
+
// signTransaction generates -- see this method's own doc comment for why no ordinary
|
|
1220
|
+
// account-key signature is added.
|
|
1221
|
+
const oneTimeSigner = (publicNonceHex) => ({
|
|
1222
|
+
getAddress: async () => walletAddress,
|
|
1223
|
+
getPublicKey: async () => parseOotleAddress(walletAddress).owner_key,
|
|
1224
|
+
signTransaction: async (tx, sealPublicKey) => {
|
|
1225
|
+
const json = serializeUnsignedTx(tx);
|
|
1226
|
+
const sig = await this.signer.addStealthSignature(json, fromHex(publicNonceHex), sealPublicKey, { crypto });
|
|
1227
|
+
return [sig];
|
|
1228
|
+
},
|
|
1229
|
+
});
|
|
1230
|
+
// Each stealth input's own sender_public_nonce lives on its UTXO substate -- fetched again
|
|
1231
|
+
// here (decryptOwnedUtxo above didn't return it) rather than parsed out of the substate
|
|
1232
|
+
// response type, whose shape `decryptOwnedUtxo` already validated once.
|
|
1233
|
+
const redeemedSubstate = await provider.getSubstate(redeemed.substateId);
|
|
1234
|
+
const feeInputSubstate = await provider.getSubstate(feeInput.substateId);
|
|
1235
|
+
const redeemedNonce = redeemedSubstate.substate.Utxo
|
|
1236
|
+
.output.output.public_nonce;
|
|
1237
|
+
const feeNonce = feeInputSubstate.substate.Utxo.output
|
|
1238
|
+
.output.public_nonce;
|
|
1239
|
+
const signed = await signTransaction([oneTimeSigner(redeemedNonce), oneTimeSigner(feeNonce)], unsignedTx);
|
|
1240
|
+
const envelope = sealTransaction(signed);
|
|
1241
|
+
const transactionId = await submitTransaction(provider, envelope);
|
|
1242
|
+
const response = await withTimeout(pollTransactionResult(provider, transactionId), 60_000, "submitting the private-fee redemption transaction");
|
|
1243
|
+
await recordKnownVersions(response);
|
|
1244
|
+
return { transactionId, feeChangeCommitment };
|
|
1245
|
+
}
|
|
1101
1246
|
/**
|
|
1102
1247
|
* Funds an HTLC (hashed timelock contract): creates a stealth output for `amount` of
|
|
1103
1248
|
* `resourceAddress`, gated not by a normal one-time stealth key but by a two-leaf TIP-0006
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chironbuilder/ootle-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Shared TypeScript client for Tari Ootle (L2): account derivation, balances, transactions, HTLCs, and stealth/confidential transfers — the account core behind Sapient and the Tari L1 web wallet's Ootle support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|