@bounded-sh/core 0.0.106 → 0.0.108
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/client/operations.d.ts +9 -1
- package/dist/client/solana-operations.d.ts +8 -2
- package/dist/client/solana-v1-operations.d.ts +2 -1
- package/dist/client/write-outcome.d.ts +32 -0
- package/dist/{index-62gjQH30.js → index-BawH-9Rq.js} +220 -194
- package/dist/index-BawH-9Rq.js.map +1 -0
- package/dist/{index-CLst0IiM.mjs → index-No5Vz0YM.mjs} +218 -193
- package/dist/index-No5Vz0YM.mjs.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{realtime-store-9SCt1RPf.js → realtime-store-D_M3T5mH.js} +2 -2
- package/dist/{realtime-store-9SCt1RPf.js.map → realtime-store-D_M3T5mH.js.map} +1 -1
- package/dist/{realtime-store-C9AgPg7U.mjs → realtime-store-iXGbzhjG.mjs} +2 -2
- package/dist/{realtime-store-C9AgPg7U.mjs.map → realtime-store-iXGbzhjG.mjs.map} +1 -1
- package/dist/{solana-message-Deru1tF1.mjs → solana-message-BBKdydqt.mjs} +2 -2
- package/dist/{solana-message-Deru1tF1.mjs.map → solana-message-BBKdydqt.mjs.map} +1 -1
- package/dist/{solana-message-Bf2q_JO1.js → solana-message-DQVrh3NC.js} +2 -2
- package/dist/{solana-message-Bf2q_JO1.js.map → solana-message-DQVrh3NC.js.map} +1 -1
- package/dist/{solana-operations-eTiLgak2.js → solana-operations-CIiyUG3b.js} +63 -16
- package/dist/solana-operations-CIiyUG3b.js.map +1 -0
- package/dist/{solana-operations-Cm19J14R.mjs → solana-operations-Dtow91W5.mjs} +61 -15
- package/dist/solana-operations-Dtow91W5.mjs.map +1 -0
- package/dist/{solana-v1-operations-Dxs4XM_F.mjs → solana-v1-operations-BF5aGRmx.mjs} +9 -8
- package/dist/solana-v1-operations-BF5aGRmx.mjs.map +1 -0
- package/dist/{solana-v1-operations-CnmiKiyj.js → solana-v1-operations-DfZr0cjj.js} +10 -9
- package/dist/solana-v1-operations-DfZr0cjj.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
- package/dist/index-62gjQH30.js.map +0 -1
- package/dist/index-CLst0IiM.mjs.map +0 -1
- package/dist/solana-operations-Cm19J14R.mjs.map +0 -1
- package/dist/solana-operations-eTiLgak2.js.map +0 -1
- package/dist/solana-v1-operations-CnmiKiyj.js.map +0 -1
- package/dist/solana-v1-operations-Dxs4XM_F.mjs.map +0 -1
|
@@ -4190,7 +4190,7 @@ class ServerSessionManager {
|
|
|
4190
4190
|
const sessionConfig = (_a = this.sessionConfig) !== null && _a !== void 0 ? _a : undefined;
|
|
4191
4191
|
/* fetch nonce from auth API (bound to the snapshotted app+issuer) */
|
|
4192
4192
|
const nonce = await genAuthNonce(sessionConfig);
|
|
4193
|
-
const { genSolanaMessage } = await Promise.resolve().then(function () { return require('./solana-message-
|
|
4193
|
+
const { genSolanaMessage } = await Promise.resolve().then(function () { return require('./solana-message-DQVrh3NC.js'); });
|
|
4194
4194
|
const message = await genSolanaMessage(address, nonce, sessionConfig === null || sessionConfig === void 0 ? void 0 : sessionConfig.appId);
|
|
4195
4195
|
/* sign the message */
|
|
4196
4196
|
const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), kp.secretKey);
|
|
@@ -7469,7 +7469,7 @@ async function doReconnectWithNewAuth() {
|
|
|
7469
7469
|
console.warn('[WS v2] Failed to clear HTTP read cache on auth change:', error);
|
|
7470
7470
|
}
|
|
7471
7471
|
try {
|
|
7472
|
-
const { reconnectRealtimeStoreWithNewAuth } = await Promise.resolve().then(function () { return require('./realtime-store-
|
|
7472
|
+
const { reconnectRealtimeStoreWithNewAuth } = await Promise.resolve().then(function () { return require('./realtime-store-D_M3T5mH.js'); });
|
|
7473
7473
|
await reconnectRealtimeStoreWithNewAuth();
|
|
7474
7474
|
}
|
|
7475
7475
|
catch (error) {
|
|
@@ -7697,6 +7697,37 @@ async function wsIntentReliable(appId, roomRoutePath, intent, isServer) {
|
|
|
7697
7697
|
});
|
|
7698
7698
|
}
|
|
7699
7699
|
|
|
7700
|
+
const PHASES = new Set(['before_broadcast', 'broadcast_rejected', 'failed_onchain']);
|
|
7701
|
+
/** Tag `error` as definitively not applied. An already-tagged error keeps its (earlier, more precise) phase. */
|
|
7702
|
+
function markWriteNotApplied(error, phase) {
|
|
7703
|
+
var _a;
|
|
7704
|
+
if (writeNotAppliedPhase(error) !== null)
|
|
7705
|
+
return error;
|
|
7706
|
+
const target = error !== null && typeof error === 'object'
|
|
7707
|
+
? error
|
|
7708
|
+
: new Error(String(error));
|
|
7709
|
+
try {
|
|
7710
|
+
Object.assign(target, { writeOutcome: 'not_applied', writePhase: phase });
|
|
7711
|
+
}
|
|
7712
|
+
catch (_b) {
|
|
7713
|
+
// A frozen throwable cannot carry the tag; wrap it so the verdict is not lost.
|
|
7714
|
+
const wrapped = new Error(String((_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error));
|
|
7715
|
+
return Object.assign(wrapped, { cause: error, writeOutcome: 'not_applied', writePhase: phase });
|
|
7716
|
+
}
|
|
7717
|
+
return target;
|
|
7718
|
+
}
|
|
7719
|
+
/** The phase a write stopped at when it was definitively not applied, else `null` (ambiguous or not a write error). */
|
|
7720
|
+
function writeNotAppliedPhase(error) {
|
|
7721
|
+
if (error === null || typeof error !== 'object')
|
|
7722
|
+
return null;
|
|
7723
|
+
const outcome = error.writeOutcome;
|
|
7724
|
+
const phase = error.writePhase;
|
|
7725
|
+
return outcome === 'not_applied' && typeof phase === 'string' && PHASES.has(phase) ? phase : null;
|
|
7726
|
+
}
|
|
7727
|
+
function isWriteNotApplied(error) {
|
|
7728
|
+
return writeNotAppliedPhase(error) !== null;
|
|
7729
|
+
}
|
|
7730
|
+
|
|
7700
7731
|
/**
|
|
7701
7732
|
* Thrown when a user's wallet doesn't have enough SOL to cover the transaction.
|
|
7702
7733
|
* Apps can catch this to trigger an onramp/funding flow.
|
|
@@ -8862,7 +8893,13 @@ async function setMany(many, options) {
|
|
|
8862
8893
|
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 402 && (error === null || error === void 0 ? void 0 : error.error) === 'INSUFFICIENT_BALANCE') {
|
|
8863
8894
|
const deficitLamports = Number((_e = error.deficitLamports) !== null && _e !== void 0 ? _e : 0);
|
|
8864
8895
|
const deficitSol = Number((_f = error.deficitSol) !== null && _f !== void 0 ? _f : deficitLamports / 1000000000);
|
|
8865
|
-
throw new InsufficientBalanceError(String((_g = error.address) !== null && _g !== void 0 ? _g : ''), Number((_h = error.balanceLamports) !== null && _h !== void 0 ? _h : 0), Number((_j = error.estimatedCostLamports) !== null && _j !== void 0 ? _j : 0), deficitLamports, deficitSol);
|
|
8896
|
+
throw markWriteNotApplied(new InsufficientBalanceError(String((_g = error.address) !== null && _g !== void 0 ? _g : ''), Number((_h = error.balanceLamports) !== null && _h !== void 0 ? _h : 0), Number((_j = error.estimatedCostLamports) !== null && _j !== void 0 ? _j : 0), deficitLamports, deficitSol), 'before_broadcast');
|
|
8897
|
+
}
|
|
8898
|
+
// The server answered and refused the write (a rule or invariant denial, a bad request, no
|
|
8899
|
+
// session, a rate limit): nothing was built, signed or committed. A network failure, a 5xx,
|
|
8900
|
+
// a 408 or a 499 may follow a commit the response never reported, so those stay untagged.
|
|
8901
|
+
if (DEFINITIVE_WRITE_REFUSAL_STATUSES.has(Number(error === null || error === void 0 ? void 0 : error.statusCode))) {
|
|
8902
|
+
throw markWriteNotApplied(error, 'before_broadcast');
|
|
8866
8903
|
}
|
|
8867
8904
|
throw error;
|
|
8868
8905
|
}
|
|
@@ -8873,118 +8910,142 @@ async function setMany(many, options) {
|
|
|
8873
8910
|
if (setResponse.status === 202) {
|
|
8874
8911
|
// This means that the document needs to be set on-chain (or signed for offchain),
|
|
8875
8912
|
// the API did nothing and gave us the required info to run this transaction.
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
// (the realtime worker commits poofnet writes directly). Fail loudly
|
|
8884
|
-
// rather than silently ignoring a payload the caller was asked to sign.
|
|
8885
|
-
throw new Error('Unsupported 202 transaction shape: offchain signing is retired');
|
|
8886
|
-
}
|
|
8887
|
-
// Handle Solana on-chain transaction flow
|
|
8888
|
-
if (!Array.isArray(transactions) || transactions.length !== 1) {
|
|
8889
|
-
throw new Error(`Expected exactly one on-chain transaction, received ${Array.isArray(transactions) ? transactions.length : 0}`);
|
|
8890
|
-
}
|
|
8891
|
-
const curTx = transactions[0];
|
|
8892
|
-
// The EVM onchain data plane is retired: no worker mints an EVM 202 any
|
|
8893
|
-
// more. A payload that still carries one is an unexpected response and
|
|
8894
|
-
// fails loudly BEFORE anything is signed - never silently ignored.
|
|
8895
|
-
if ((curTx === null || curTx === void 0 ? void 0 : curTx.evmTransaction) != null) {
|
|
8896
|
-
throw new Error('Unsupported 202 transaction shape: the write response carried an evmTransaction, ' +
|
|
8897
|
-
'but EVM onchain writes are no longer supported. Nothing was signed or submitted.');
|
|
8898
|
-
}
|
|
8899
|
-
const hasSerializedSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.serializedTransaction) != null;
|
|
8900
|
-
const hasBuiltSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.transactionArgs) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.remainingAccounts) != null ||
|
|
8901
|
-
(curTx === null || curTx === void 0 ? void 0 : curTx.idl) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.txData) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.preInstructions) != null;
|
|
8902
|
-
if (hasSerializedSolanaTarget && hasBuiltSolanaTarget) {
|
|
8903
|
-
throw new Error('Ambiguous on-chain write response mixes Solana transaction target formats');
|
|
8904
|
-
}
|
|
8905
|
-
// All requested paths (writes AND deletes), in request order. Used for the
|
|
8906
|
-
// post-confirm mirror read-back, which correlates every requested path.
|
|
8907
|
-
// The pre-sign validation derives its own full expected intent from
|
|
8908
|
-
// `documents` (see below) and needs nothing from this list.
|
|
8909
|
-
const requestedPaths = documents.map(d => d.destinationPath);
|
|
8910
|
-
const requestedDocuments = buildRequestedDocuments(documents);
|
|
8911
|
-
const appId = config.appId;
|
|
8912
|
-
// The lane comes verbatim from the worker, and is read BEFORE anything is
|
|
8913
|
-
// signed or submitted: a missing tag fails closed while nothing has been
|
|
8914
|
-
// broadcast, instead of stranding a landed transaction with no receipt.
|
|
8915
|
-
const workerChain = readWorkerChainTag((_k = setResponse.data) === null || _k === void 0 ? void 0 : _k.receipt, setResponse.data, curTx);
|
|
8916
|
-
if (!workerChain) {
|
|
8917
|
-
throw new Error('The write response carried no execution-chain tag, so this receipt could not state where the write ran. ' +
|
|
8918
|
-
'Nothing was signed or submitted.');
|
|
8919
|
-
}
|
|
8920
|
-
if (workerChain === 'realtime_offchain') {
|
|
8921
|
-
// Poofnet: the wallet signs the worker's unsendable approval message and
|
|
8922
|
-
// the worker verifies and commits it. Nothing is submitted to any chain.
|
|
8923
|
-
if (typeof curTx.serializedTransaction !== 'string' || typeof curTx.poofnetIntentId !== 'string') {
|
|
8924
|
-
throw new Error('Unsupported 202 transaction shape: a poofnet write needs serializedTransaction and poofnetIntentId');
|
|
8913
|
+
// Until something is sent, every failure below is definitively not applied.
|
|
8914
|
+
let sending = false;
|
|
8915
|
+
try {
|
|
8916
|
+
const { transactions, offchainTransaction } = setResponse.data;
|
|
8917
|
+
// Handle offchain transaction flow (for 'offchain' protocol apps)
|
|
8918
|
+
if (offchainTransaction && Array.isArray(transactions) && transactions.length > 0) {
|
|
8919
|
+
throw new Error('Ambiguous write response mixes offchain and onchain transaction targets');
|
|
8925
8920
|
}
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
status: 'signed', appId, requestedDocuments: buildRequestedDocuments(documents),
|
|
8932
|
-
chain: 'realtime_offchain', transactionId: null, signedTransaction,
|
|
8933
|
-
poofnetIntentId: curTx.poofnetIntentId,
|
|
8934
|
-
};
|
|
8921
|
+
if (offchainTransaction) {
|
|
8922
|
+
// Offchain signing is retired: no server mints this envelope any more
|
|
8923
|
+
// (the realtime worker commits poofnet writes directly). Fail loudly
|
|
8924
|
+
// rather than silently ignoring a payload the caller was asked to sign.
|
|
8925
|
+
throw new Error('Unsupported 202 transaction shape: offchain signing is retired');
|
|
8935
8926
|
}
|
|
8936
|
-
|
|
8937
|
-
if (
|
|
8938
|
-
throw new Error(`
|
|
8927
|
+
// Handle Solana on-chain transaction flow
|
|
8928
|
+
if (!Array.isArray(transactions) || transactions.length !== 1) {
|
|
8929
|
+
throw new Error(`Expected exactly one on-chain transaction, received ${Array.isArray(transactions) ? transactions.length : 0}`);
|
|
8939
8930
|
}
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8931
|
+
const curTx = transactions[0];
|
|
8932
|
+
// The EVM onchain data plane is retired: no worker mints an EVM 202 any
|
|
8933
|
+
// more. A payload that still carries one is an unexpected response and
|
|
8934
|
+
// fails loudly BEFORE anything is signed - never silently ignored.
|
|
8935
|
+
if ((curTx === null || curTx === void 0 ? void 0 : curTx.evmTransaction) != null) {
|
|
8936
|
+
throw new Error('Unsupported 202 transaction shape: the write response carried an evmTransaction, ' +
|
|
8937
|
+
'but EVM onchain writes are no longer supported. Nothing was signed or submitted.');
|
|
8938
|
+
}
|
|
8939
|
+
const hasSerializedSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.serializedTransaction) != null;
|
|
8940
|
+
const hasBuiltSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.transactionArgs) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.remainingAccounts) != null ||
|
|
8941
|
+
(curTx === null || curTx === void 0 ? void 0 : curTx.idl) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.txData) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.preInstructions) != null;
|
|
8942
|
+
if (hasSerializedSolanaTarget && hasBuiltSolanaTarget) {
|
|
8943
|
+
throw new Error('Ambiguous on-chain write response mixes Solana transaction target formats');
|
|
8944
|
+
}
|
|
8945
|
+
// All requested paths (writes AND deletes), in request order. Used for the
|
|
8946
|
+
// post-confirm mirror read-back, which correlates every requested path.
|
|
8947
|
+
// The pre-sign validation derives its own full expected intent from
|
|
8948
|
+
// `documents` (see below) and needs nothing from this list.
|
|
8949
|
+
const requestedPaths = documents.map(d => d.destinationPath);
|
|
8950
|
+
const requestedDocuments = buildRequestedDocuments(documents);
|
|
8951
|
+
const appId = config.appId;
|
|
8952
|
+
// The lane comes verbatim from the worker, and is read BEFORE anything is
|
|
8953
|
+
// signed or submitted: a missing tag fails closed while nothing has been
|
|
8954
|
+
// broadcast, instead of stranding a landed transaction with no receipt.
|
|
8955
|
+
const workerChain = readWorkerChainTag((_k = setResponse.data) === null || _k === void 0 ? void 0 : _k.receipt, setResponse.data, curTx);
|
|
8956
|
+
if (!workerChain) {
|
|
8957
|
+
throw new Error('The write response carried no execution-chain tag, so this receipt could not state where the write ran. ' +
|
|
8945
8958
|
'Nothing was signed or submitted.');
|
|
8946
8959
|
}
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8960
|
+
if (workerChain === 'realtime_offchain') {
|
|
8961
|
+
// Poofnet: the wallet signs the worker's unsendable approval message and
|
|
8962
|
+
// the worker verifies and commits it. Nothing is submitted to any chain.
|
|
8963
|
+
if (typeof curTx.serializedTransaction !== 'string' || typeof curTx.poofnetIntentId !== 'string') {
|
|
8964
|
+
throw new Error('Unsupported 202 transaction shape: a poofnet write needs serializedTransaction and poofnetIntentId');
|
|
8965
|
+
}
|
|
8966
|
+
const { signPoofnetTransaction, buildExpectedWriteIntent } = await Promise.resolve().then(function () { return require('./solana-operations-CIiyUG3b.js'); });
|
|
8967
|
+
const signedTransaction = await signPoofnetTransaction(curTx.serializedTransaction, authProvider, options, buildExpectedWriteIntent(documents));
|
|
8968
|
+
// Signing-only, exactly as on a real chain: signed and NOT committed.
|
|
8969
|
+
if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
|
|
8970
|
+
return {
|
|
8971
|
+
status: 'signed', appId, requestedDocuments: buildRequestedDocuments(documents),
|
|
8972
|
+
chain: 'realtime_offchain', transactionId: null, signedTransaction,
|
|
8973
|
+
poofnetIntentId: curTx.poofnetIntentId,
|
|
8974
|
+
};
|
|
8975
|
+
}
|
|
8976
|
+
// The commit PUT is the one ambiguous step of this lane: a lost response
|
|
8977
|
+
// may follow a commit, so its failures stay untagged (read the path back).
|
|
8978
|
+
sending = true;
|
|
8979
|
+
const commitResponse = await makeApiRequest('PUT', 'items/signed', { intentId: curTx.poofnetIntentId, signedTransaction }, options === null || options === void 0 ? void 0 : options._overrides);
|
|
8980
|
+
if (commitResponse.status !== 200) {
|
|
8981
|
+
throw new Error(`Poofnet signed write was not committed (status ${commitResponse.status})`);
|
|
8982
|
+
}
|
|
8983
|
+
return directCommitResult(commitResponse, documents);
|
|
8964
8984
|
}
|
|
8965
|
-
if (
|
|
8985
|
+
if (curTx.serializedTransaction) {
|
|
8986
|
+
if (!SOLANA_CHAIN_TAGS.has(workerChain)) {
|
|
8987
|
+
throw new Error(`The write response reported execution chain "${workerChain}" for a Solana transaction. ` +
|
|
8988
|
+
'Nothing was signed or submitted.');
|
|
8989
|
+
}
|
|
8990
|
+
const solanaChain = workerChain;
|
|
8991
|
+
const { handlePreBuiltTransaction, buildExpectedWriteIntent } = await Promise.resolve().then(function () { return require('./solana-operations-CIiyUG3b.js'); });
|
|
8992
|
+
// OA-0001: derive the expected intent from OUR OWN request (the one
|
|
8993
|
+
// ground truth a tampered builder response cannot change) so the
|
|
8994
|
+
// validator can reject any transaction whose operation semantics
|
|
8995
|
+
// diverge from it BEFORE the wallet is asked to sign.
|
|
8996
|
+
const expectedIntent = buildExpectedWriteIntent(documents);
|
|
8997
|
+
const onBroadcast = options === null || options === void 0 ? void 0 : options.onBroadcast;
|
|
8998
|
+
const solanaOutcome = await handlePreBuiltTransaction(curTx, authProvider, options, expectedIntent, onBroadcast && (async (signed) => {
|
|
8999
|
+
await onBroadcast({
|
|
9000
|
+
status: 'submitted', appId, requestedDocuments, chain: solanaChain,
|
|
9001
|
+
transactionId: signed.transactionSignature,
|
|
9002
|
+
signedTransaction: signed.signedTransaction,
|
|
9003
|
+
fence: signed.fence,
|
|
9004
|
+
confirmation: { state: 'unknown', reason: 'about to broadcast' },
|
|
9005
|
+
});
|
|
9006
|
+
}));
|
|
9007
|
+
// Past this point the bytes may be on the network: nothing is tagged here.
|
|
9008
|
+
sending = true;
|
|
9009
|
+
// `shouldSubmitTx: false` signed WITHOUT sending — no signature exists,
|
|
9010
|
+
// and there is nothing to mirror, so no synchronization is attempted.
|
|
9011
|
+
if (solanaOutcome.outcome === 'signed') {
|
|
9012
|
+
return {
|
|
9013
|
+
status: 'signed', appId, requestedDocuments, chain: solanaChain,
|
|
9014
|
+
transactionId: null,
|
|
9015
|
+
signedTransaction: solanaOutcome.signedTransaction,
|
|
9016
|
+
fence: solanaOutcome.fence,
|
|
9017
|
+
};
|
|
9018
|
+
}
|
|
9019
|
+
if (solanaOutcome.outcome === 'submitted') {
|
|
9020
|
+
return {
|
|
9021
|
+
status: 'submitted', appId, requestedDocuments, chain: solanaChain,
|
|
9022
|
+
transactionId: solanaOutcome.transactionSignature,
|
|
9023
|
+
signedTransaction: solanaOutcome.signedTransaction,
|
|
9024
|
+
fence: solanaOutcome.fence,
|
|
9025
|
+
confirmation: { state: 'unknown', reason: solanaOutcome.reason },
|
|
9026
|
+
};
|
|
9027
|
+
}
|
|
9028
|
+
// Confirmed: the receipt is already complete, so the mirror read is a
|
|
9029
|
+
// best-effort enrichment reported in `mirrorSync`, never a rejection.
|
|
9030
|
+
const mirrorSync = await attemptMirrorSync(requestedPaths, options);
|
|
8966
9031
|
return {
|
|
8967
|
-
status: '
|
|
9032
|
+
status: 'confirmed', appId, requestedDocuments, chain: solanaChain,
|
|
8968
9033
|
transactionId: solanaOutcome.transactionSignature,
|
|
8969
9034
|
signedTransaction: solanaOutcome.signedTransaction,
|
|
8970
9035
|
fence: solanaOutcome.fence,
|
|
8971
|
-
|
|
9036
|
+
confirmationContextSlot: solanaOutcome.confirmationContextSlot,
|
|
9037
|
+
mirrorSync,
|
|
8972
9038
|
};
|
|
8973
9039
|
}
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
return {
|
|
8978
|
-
status: 'confirmed', appId, requestedDocuments, chain: solanaChain,
|
|
8979
|
-
transactionId: solanaOutcome.transactionSignature,
|
|
8980
|
-
signedTransaction: solanaOutcome.signedTransaction,
|
|
8981
|
-
fence: solanaOutcome.fence,
|
|
8982
|
-
confirmationContextSlot: solanaOutcome.confirmationContextSlot,
|
|
8983
|
-
mirrorSync,
|
|
8984
|
-
};
|
|
9040
|
+
else {
|
|
9041
|
+
throw new Error('Unsupported 202 transaction shape: expected serializedTransaction');
|
|
9042
|
+
}
|
|
8985
9043
|
}
|
|
8986
|
-
|
|
8987
|
-
|
|
9044
|
+
catch (error) {
|
|
9045
|
+
// The Solana lane tags its own broadcast and on-chain failures; anything
|
|
9046
|
+
// untagged from it, and every poofnet step before the commit PUT, failed
|
|
9047
|
+
// before a single byte was sent.
|
|
9048
|
+
throw sending ? error : markWriteNotApplied(error, 'before_broadcast');
|
|
8988
9049
|
}
|
|
8989
9050
|
}
|
|
8990
9051
|
else if (setResponse.status === 200) {
|
|
@@ -9005,6 +9066,8 @@ async function setMany(many, options) {
|
|
|
9005
9066
|
* of a result document (a delete returns the PREVIOUS document, so its stale
|
|
9006
9067
|
* `_transaction_hash` would misreport the delete).
|
|
9007
9068
|
*/
|
|
9069
|
+
/** HTTP statuses on the write request that prove the server refused it before anything happened. */
|
|
9070
|
+
const DEFINITIVE_WRITE_REFUSAL_STATUSES = new Set([400, 401, 402, 403, 404, 409, 422, 429]);
|
|
9008
9071
|
function directCommitResult(response, documents) {
|
|
9009
9072
|
var _a;
|
|
9010
9073
|
const body = (response.data && typeof response.data === 'object' && !Array.isArray(response.data))
|
|
@@ -9273,48 +9336,6 @@ var operations = /*#__PURE__*/Object.freeze({
|
|
|
9273
9336
|
syncItems: syncItems
|
|
9274
9337
|
});
|
|
9275
9338
|
|
|
9276
|
-
/** The highest Solana transaction version this SDK reads back (SIMD-0385 v1). */
|
|
9277
|
-
const SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION = 1;
|
|
9278
|
-
/**
|
|
9279
|
-
* getTransaction that survives a SIMD-0385 v1 response. @solana/web3.js 1.98.x
|
|
9280
|
-
* validates `version` against `0 | 'legacy'` and THROWS on 1 even when the request
|
|
9281
|
-
* raised the ceiling, so a real `Connection` (which exposes `rpcEndpoint`) is read
|
|
9282
|
-
* as raw JSON-RPC instead. An injected double without an endpoint goes through its
|
|
9283
|
-
* own `getTransaction` with the ceiling raised. Returns the RPC `result` (null when
|
|
9284
|
-
* the signature is unknown); RPC and transport failures throw so callers keep
|
|
9285
|
-
* treating a failed lookup as inconclusive rather than as absence.
|
|
9286
|
-
*/
|
|
9287
|
-
async function getTransactionJson(rpc, signature, commitment = 'confirmed') {
|
|
9288
|
-
var _a;
|
|
9289
|
-
const endpoint = typeof (rpc === null || rpc === void 0 ? void 0 : rpc.rpcEndpoint) === 'string' ? rpc.rpcEndpoint.trim() : '';
|
|
9290
|
-
if (!endpoint) {
|
|
9291
|
-
return rpc.getTransaction(signature, {
|
|
9292
|
-
maxSupportedTransactionVersion: SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION,
|
|
9293
|
-
commitment,
|
|
9294
|
-
});
|
|
9295
|
-
}
|
|
9296
|
-
const response = await fetch(endpoint, {
|
|
9297
|
-
method: 'POST',
|
|
9298
|
-
headers: { 'content-type': 'application/json' },
|
|
9299
|
-
body: JSON.stringify({
|
|
9300
|
-
jsonrpc: '2.0',
|
|
9301
|
-
id: 1,
|
|
9302
|
-
method: 'getTransaction',
|
|
9303
|
-
params: [signature, {
|
|
9304
|
-
commitment,
|
|
9305
|
-
encoding: 'json',
|
|
9306
|
-
maxSupportedTransactionVersion: SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION,
|
|
9307
|
-
}],
|
|
9308
|
-
}),
|
|
9309
|
-
});
|
|
9310
|
-
if (!response.ok)
|
|
9311
|
-
throw new Error(`getTransaction http ${response.status}`);
|
|
9312
|
-
const body = await response.json();
|
|
9313
|
-
if (body === null || body === void 0 ? void 0 : body.error)
|
|
9314
|
-
throw new Error(`getTransaction rpc error ${body.error.code}: ${body.error.message}`);
|
|
9315
|
-
return (_a = body === null || body === void 0 ? void 0 : body.result) !== null && _a !== void 0 ? _a : null;
|
|
9316
|
-
}
|
|
9317
|
-
|
|
9318
9339
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
9319
9340
|
const DEFAULT_MAX_ATTEMPTS$1 = 20;
|
|
9320
9341
|
const DEFAULT_POLL_INTERVAL_MS = 3000;
|
|
@@ -9388,20 +9409,50 @@ async function resolveSolanaRpc(config, options) {
|
|
|
9388
9409
|
return new Connection(rpcUrl, 'confirmed');
|
|
9389
9410
|
}
|
|
9390
9411
|
/**
|
|
9391
|
-
*
|
|
9392
|
-
*
|
|
9393
|
-
*
|
|
9412
|
+
* Whether a signature status is final enough to decide on. `processed` can still belong to a fork
|
|
9413
|
+
* that is dropped, so only `confirmed` or `finalized` settle a write; an RPC that omits
|
|
9414
|
+
* `confirmationStatus` reports a rooted transaction as `confirmations: null`.
|
|
9415
|
+
*/
|
|
9416
|
+
function settledStatus(status) {
|
|
9417
|
+
if (!status)
|
|
9418
|
+
return false;
|
|
9419
|
+
if (status.confirmationStatus === 'confirmed' || status.confirmationStatus === 'finalized')
|
|
9420
|
+
return true;
|
|
9421
|
+
return status.confirmationStatus == null && status.confirmations === null;
|
|
9422
|
+
}
|
|
9423
|
+
/**
|
|
9424
|
+
* Solana reconciliation NEVER broadcasts. It settles on a `confirmed` or `finalized` status only,
|
|
9425
|
+
* and reaches `expired_not_landed` only from the chain's own blockhash expiry: the FINALIZED block
|
|
9426
|
+
* height is past the fence, so the network can never accept these bytes again, and a
|
|
9427
|
+
* history-searching status lookup from a node that has seen that finalized slot finds no record.
|
|
9428
|
+
* Anything short of that - a `processed` status, a lookup that fails, a node behind the expiry
|
|
9429
|
+
* point - stays `submitted`.
|
|
9394
9430
|
*/
|
|
9395
9431
|
async function reconcileSolana(receipt, config, options) {
|
|
9396
9432
|
var _a, _b, _c, _d;
|
|
9397
9433
|
const rpc = await resolveSolanaRpc(config, options);
|
|
9434
|
+
if (typeof rpc.getSignatureStatuses !== 'function') {
|
|
9435
|
+
return stillSubmitted(receipt, 'the configured Solana RPC cannot report signature statuses');
|
|
9436
|
+
}
|
|
9437
|
+
// Expiry is read BEFORE the status, so an absence observed afterwards is an absence after the
|
|
9438
|
+
// fence closed for good. A finalized height past lastValidBlockHeight is final: the blockhash
|
|
9439
|
+
// can never become valid again.
|
|
9440
|
+
let finalizedHeight;
|
|
9441
|
+
let finalizedSlot;
|
|
9442
|
+
try {
|
|
9443
|
+
if (typeof rpc.getBlockHeight === 'function')
|
|
9444
|
+
finalizedHeight = await rpc.getBlockHeight('finalized');
|
|
9445
|
+
if (typeof rpc.getSlot === 'function')
|
|
9446
|
+
finalizedSlot = await rpc.getSlot('finalized');
|
|
9447
|
+
}
|
|
9448
|
+
catch (error) {
|
|
9449
|
+
return stillSubmitted(receipt, `finalized height lookup failed: ${errorText(error)}`);
|
|
9450
|
+
}
|
|
9451
|
+
const expired = typeof finalizedHeight === 'number' && finalizedHeight > receipt.fence.lastValidBlockHeight;
|
|
9398
9452
|
let statusValue = null;
|
|
9399
9453
|
let contextSlot;
|
|
9400
9454
|
try {
|
|
9401
|
-
|
|
9402
|
-
return stillSubmitted(receipt, 'the configured Solana RPC cannot report signature statuses');
|
|
9403
|
-
}
|
|
9404
|
-
const statuses = await rpc.getSignatureStatuses([receipt.transactionId]);
|
|
9455
|
+
const statuses = await rpc.getSignatureStatuses([receipt.transactionId], { searchTransactionHistory: true });
|
|
9405
9456
|
statusValue = (_b = (_a = statuses === null || statuses === void 0 ? void 0 : statuses.value) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null;
|
|
9406
9457
|
contextSlot = (_c = statuses === null || statuses === void 0 ? void 0 : statuses.context) === null || _c === void 0 ? void 0 : _c.slot;
|
|
9407
9458
|
}
|
|
@@ -9409,9 +9460,12 @@ async function reconcileSolana(receipt, config, options) {
|
|
|
9409
9460
|
return stillSubmitted(receipt, `signature status lookup failed: ${errorText(error)}`);
|
|
9410
9461
|
}
|
|
9411
9462
|
if (statusValue) {
|
|
9463
|
+
if (!settledStatus(statusValue)) {
|
|
9464
|
+
return stillSubmitted(receipt, `seen at ${String((_d = statusValue.confirmationStatus) !== null && _d !== void 0 ? _d : 'an unconfirmed')} commitment; waiting for confirmed`);
|
|
9465
|
+
}
|
|
9412
9466
|
// Landed. A landed-but-failed transaction is a genuine failure, not `submitted`.
|
|
9413
9467
|
if (statusValue.err) {
|
|
9414
|
-
throw new Error(`Transaction failed: ${JSON.stringify(statusValue.err)}`);
|
|
9468
|
+
throw markWriteNotApplied(new Error(`Transaction failed: ${JSON.stringify(statusValue.err)}`), 'failed_onchain');
|
|
9415
9469
|
}
|
|
9416
9470
|
const confirmed = {
|
|
9417
9471
|
status: 'confirmed',
|
|
@@ -9421,50 +9475,21 @@ async function reconcileSolana(receipt, config, options) {
|
|
|
9421
9475
|
transactionId: receipt.transactionId,
|
|
9422
9476
|
signedTransaction: receipt.signedTransaction,
|
|
9423
9477
|
fence: receipt.fence,
|
|
9424
|
-
confirmationContextSlot: contextSlot !== null && contextSlot !== void 0 ? contextSlot : 0,
|
|
9478
|
+
confirmationContextSlot: typeof statusValue.slot === 'number' ? statusValue.slot : (contextSlot !== null && contextSlot !== void 0 ? contextSlot : 0),
|
|
9425
9479
|
mirrorSync: await mirrorFor(receipt, options),
|
|
9426
9480
|
};
|
|
9427
9481
|
return confirmed;
|
|
9428
9482
|
}
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
let blockHeight;
|
|
9432
|
-
try {
|
|
9433
|
-
blockHeight = typeof rpc.getBlockHeight === 'function' ? await rpc.getBlockHeight('confirmed') : undefined;
|
|
9483
|
+
if (typeof finalizedHeight !== 'number') {
|
|
9484
|
+
return stillSubmitted(receipt, 'expiry could not be observed: the RPC reported no finalized block height');
|
|
9434
9485
|
}
|
|
9435
|
-
|
|
9436
|
-
return stillSubmitted(receipt, `block height
|
|
9437
|
-
}
|
|
9438
|
-
if (typeof blockHeight !== 'number') {
|
|
9439
|
-
return stillSubmitted(receipt, 'expiry could not be observed: the RPC reported no block height');
|
|
9440
|
-
}
|
|
9441
|
-
if (blockHeight <= receipt.fence.lastValidBlockHeight) {
|
|
9442
|
-
return stillSubmitted(receipt, `not yet expired: block height ${blockHeight} is within the fence (lastValidBlockHeight ${receipt.fence.lastValidBlockHeight})`);
|
|
9443
|
-
}
|
|
9444
|
-
// Expired. Prove absence from history before declaring the write retry-safe.
|
|
9445
|
-
let history;
|
|
9446
|
-
try {
|
|
9447
|
-
history = await getTransactionJson(rpc, receipt.transactionId, 'confirmed');
|
|
9486
|
+
if (!expired) {
|
|
9487
|
+
return stillSubmitted(receipt, `not yet expired: finalized block height ${finalizedHeight} is within the fence (lastValidBlockHeight ${receipt.fence.lastValidBlockHeight})`);
|
|
9448
9488
|
}
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
if ((_d = history === null || history === void 0 ? void 0 : history.meta) === null || _d === void 0 ? void 0 : _d.err) {
|
|
9454
|
-
throw new Error(`Transaction failed: ${JSON.stringify(history.meta.err)}`);
|
|
9455
|
-
}
|
|
9456
|
-
const confirmed = {
|
|
9457
|
-
status: 'confirmed',
|
|
9458
|
-
appId: receipt.appId,
|
|
9459
|
-
requestedDocuments: receipt.requestedDocuments,
|
|
9460
|
-
chain: receipt.chain,
|
|
9461
|
-
transactionId: receipt.transactionId,
|
|
9462
|
-
signedTransaction: receipt.signedTransaction,
|
|
9463
|
-
fence: receipt.fence,
|
|
9464
|
-
confirmationContextSlot: typeof history.slot === 'number' ? history.slot : (contextSlot !== null && contextSlot !== void 0 ? contextSlot : 0),
|
|
9465
|
-
mirrorSync: await mirrorFor(receipt, options),
|
|
9466
|
-
};
|
|
9467
|
-
return confirmed;
|
|
9489
|
+
// A load-balanced RPC may answer the status from a node behind the one that reported the
|
|
9490
|
+
// finalized height. Its absence proves nothing until that node has seen the finalized slot.
|
|
9491
|
+
if (typeof finalizedSlot !== 'number' || typeof contextSlot !== 'number' || contextSlot < finalizedSlot) {
|
|
9492
|
+
return stillSubmitted(receipt, `expired, but the status node (slot ${contextSlot !== null && contextSlot !== void 0 ? contextSlot : 'unknown'}) has not reached the finalized slot ${finalizedSlot !== null && finalizedSlot !== void 0 ? finalizedSlot : 'unknown'}`);
|
|
9468
9493
|
}
|
|
9469
9494
|
return {
|
|
9470
9495
|
status: 'expired_not_landed',
|
|
@@ -10727,7 +10752,7 @@ function toMillis(seconds) {
|
|
|
10727
10752
|
|
|
10728
10753
|
/** SIWS message creation is async already, so its onchain module can be lazy. */
|
|
10729
10754
|
async function genSolanaMessage(address, nonce) {
|
|
10730
|
-
const implementation = await Promise.resolve().then(function () { return require('./solana-message-
|
|
10755
|
+
const implementation = await Promise.resolve().then(function () { return require('./solana-message-DQVrh3NC.js'); });
|
|
10731
10756
|
return implementation.genSolanaMessage(address, nonce);
|
|
10732
10757
|
}
|
|
10733
10758
|
|
|
@@ -11289,7 +11314,6 @@ exports.LiveIntentError = LiveIntentError;
|
|
|
11289
11314
|
exports.MIN_QUERY_POLL_INTERVAL_MS = MIN_QUERY_POLL_INTERVAL_MS;
|
|
11290
11315
|
exports.RATE_LIMIT_EVENT_NAME = RATE_LIMIT_EVENT_NAME;
|
|
11291
11316
|
exports.ReactNativeSessionManager = ReactNativeSessionManager;
|
|
11292
|
-
exports.SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION = SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION;
|
|
11293
11317
|
exports.SOLANA_SIGN_IN_STATEMENT = SOLANA_SIGN_IN_STATEMENT;
|
|
11294
11318
|
exports.ScopedClientReadOnlyError = ScopedClientReadOnlyError;
|
|
11295
11319
|
exports.ServerSessionManager = ServerSessionManager;
|
|
@@ -11334,7 +11358,6 @@ exports.getFreshAuthToken = getFreshAuthToken;
|
|
|
11334
11358
|
exports.getIdToken = getIdToken;
|
|
11335
11359
|
exports.getMany = getMany;
|
|
11336
11360
|
exports.getSessionGeneration = getSessionGeneration;
|
|
11337
|
-
exports.getTransactionJson = getTransactionJson;
|
|
11338
11361
|
exports.getWebhookKeysUrl = getWebhookKeysUrl;
|
|
11339
11362
|
exports.hasActiveConnection = hasActiveConnection;
|
|
11340
11363
|
exports.increment = increment;
|
|
@@ -11343,7 +11366,9 @@ exports.intent = intent;
|
|
|
11343
11366
|
exports.invoke = invoke;
|
|
11344
11367
|
exports.isAuthExpiredError = isAuthExpiredError;
|
|
11345
11368
|
exports.isEffectResult = isEffectResult;
|
|
11369
|
+
exports.isWriteNotApplied = isWriteNotApplied;
|
|
11346
11370
|
exports.live = live;
|
|
11371
|
+
exports.markWriteNotApplied = markWriteNotApplied;
|
|
11347
11372
|
exports.normalizeEvmAddress = normalizeEvmAddress;
|
|
11348
11373
|
exports.now = now;
|
|
11349
11374
|
exports.onSessionCleared = onSessionCleared;
|
|
@@ -11374,4 +11399,5 @@ exports.toMillis = toMillis;
|
|
|
11374
11399
|
exports.toSeconds = toSeconds;
|
|
11375
11400
|
exports.waitForSetResult = waitForSetResult;
|
|
11376
11401
|
exports.withEffects = withEffects;
|
|
11377
|
-
|
|
11402
|
+
exports.writeNotAppliedPhase = writeNotAppliedPhase;
|
|
11403
|
+
//# sourceMappingURL=index-BawH-9Rq.js.map
|