@bounded-sh/core 0.0.107 → 0.0.109
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
|
@@ -4188,7 +4188,7 @@ class ServerSessionManager {
|
|
|
4188
4188
|
const sessionConfig = (_a = this.sessionConfig) !== null && _a !== void 0 ? _a : undefined;
|
|
4189
4189
|
/* fetch nonce from auth API (bound to the snapshotted app+issuer) */
|
|
4190
4190
|
const nonce = await genAuthNonce(sessionConfig);
|
|
4191
|
-
const { genSolanaMessage } = await import('./solana-message-
|
|
4191
|
+
const { genSolanaMessage } = await import('./solana-message-BBKdydqt.mjs');
|
|
4192
4192
|
const message = await genSolanaMessage(address, nonce, sessionConfig === null || sessionConfig === void 0 ? void 0 : sessionConfig.appId);
|
|
4193
4193
|
/* sign the message */
|
|
4194
4194
|
const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), kp.secretKey);
|
|
@@ -7467,7 +7467,7 @@ async function doReconnectWithNewAuth() {
|
|
|
7467
7467
|
console.warn('[WS v2] Failed to clear HTTP read cache on auth change:', error);
|
|
7468
7468
|
}
|
|
7469
7469
|
try {
|
|
7470
|
-
const { reconnectRealtimeStoreWithNewAuth } = await import('./realtime-store-
|
|
7470
|
+
const { reconnectRealtimeStoreWithNewAuth } = await import('./realtime-store-iXGbzhjG.mjs');
|
|
7471
7471
|
await reconnectRealtimeStoreWithNewAuth();
|
|
7472
7472
|
}
|
|
7473
7473
|
catch (error) {
|
|
@@ -7695,6 +7695,37 @@ async function wsIntentReliable(appId, roomRoutePath, intent, isServer) {
|
|
|
7695
7695
|
});
|
|
7696
7696
|
}
|
|
7697
7697
|
|
|
7698
|
+
const PHASES = new Set(['before_broadcast', 'broadcast_rejected', 'failed_onchain']);
|
|
7699
|
+
/** Tag `error` as definitively not applied. An already-tagged error keeps its (earlier, more precise) phase. */
|
|
7700
|
+
function markWriteNotApplied(error, phase) {
|
|
7701
|
+
var _a;
|
|
7702
|
+
if (writeNotAppliedPhase(error) !== null)
|
|
7703
|
+
return error;
|
|
7704
|
+
const target = error !== null && typeof error === 'object'
|
|
7705
|
+
? error
|
|
7706
|
+
: new Error(String(error));
|
|
7707
|
+
try {
|
|
7708
|
+
Object.assign(target, { writeOutcome: 'not_applied', writePhase: phase });
|
|
7709
|
+
}
|
|
7710
|
+
catch (_b) {
|
|
7711
|
+
// A frozen throwable cannot carry the tag; wrap it so the verdict is not lost.
|
|
7712
|
+
const wrapped = new Error(String((_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error));
|
|
7713
|
+
return Object.assign(wrapped, { cause: error, writeOutcome: 'not_applied', writePhase: phase });
|
|
7714
|
+
}
|
|
7715
|
+
return target;
|
|
7716
|
+
}
|
|
7717
|
+
/** The phase a write stopped at when it was definitively not applied, else `null` (ambiguous or not a write error). */
|
|
7718
|
+
function writeNotAppliedPhase(error) {
|
|
7719
|
+
if (error === null || typeof error !== 'object')
|
|
7720
|
+
return null;
|
|
7721
|
+
const outcome = error.writeOutcome;
|
|
7722
|
+
const phase = error.writePhase;
|
|
7723
|
+
return outcome === 'not_applied' && typeof phase === 'string' && PHASES.has(phase) ? phase : null;
|
|
7724
|
+
}
|
|
7725
|
+
function isWriteNotApplied(error) {
|
|
7726
|
+
return writeNotAppliedPhase(error) !== null;
|
|
7727
|
+
}
|
|
7728
|
+
|
|
7698
7729
|
/**
|
|
7699
7730
|
* Thrown when a user's wallet doesn't have enough SOL to cover the transaction.
|
|
7700
7731
|
* Apps can catch this to trigger an onramp/funding flow.
|
|
@@ -8860,7 +8891,13 @@ async function setMany(many, options) {
|
|
|
8860
8891
|
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 402 && (error === null || error === void 0 ? void 0 : error.error) === 'INSUFFICIENT_BALANCE') {
|
|
8861
8892
|
const deficitLamports = Number((_e = error.deficitLamports) !== null && _e !== void 0 ? _e : 0);
|
|
8862
8893
|
const deficitSol = Number((_f = error.deficitSol) !== null && _f !== void 0 ? _f : deficitLamports / 1000000000);
|
|
8863
|
-
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);
|
|
8894
|
+
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');
|
|
8895
|
+
}
|
|
8896
|
+
// The server answered and refused the write (a rule or invariant denial, a bad request, no
|
|
8897
|
+
// session, a rate limit): nothing was built, signed or committed. A network failure, a 5xx,
|
|
8898
|
+
// a 408 or a 499 may follow a commit the response never reported, so those stay untagged.
|
|
8899
|
+
if (DEFINITIVE_WRITE_REFUSAL_STATUSES.has(Number(error === null || error === void 0 ? void 0 : error.statusCode))) {
|
|
8900
|
+
throw markWriteNotApplied(error, 'before_broadcast');
|
|
8864
8901
|
}
|
|
8865
8902
|
throw error;
|
|
8866
8903
|
}
|
|
@@ -8871,118 +8908,142 @@ async function setMany(many, options) {
|
|
|
8871
8908
|
if (setResponse.status === 202) {
|
|
8872
8909
|
// This means that the document needs to be set on-chain (or signed for offchain),
|
|
8873
8910
|
// the API did nothing and gave us the required info to run this transaction.
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
// (the realtime worker commits poofnet writes directly). Fail loudly
|
|
8882
|
-
// rather than silently ignoring a payload the caller was asked to sign.
|
|
8883
|
-
throw new Error('Unsupported 202 transaction shape: offchain signing is retired');
|
|
8884
|
-
}
|
|
8885
|
-
// Handle Solana on-chain transaction flow
|
|
8886
|
-
if (!Array.isArray(transactions) || transactions.length !== 1) {
|
|
8887
|
-
throw new Error(`Expected exactly one on-chain transaction, received ${Array.isArray(transactions) ? transactions.length : 0}`);
|
|
8888
|
-
}
|
|
8889
|
-
const curTx = transactions[0];
|
|
8890
|
-
// The EVM onchain data plane is retired: no worker mints an EVM 202 any
|
|
8891
|
-
// more. A payload that still carries one is an unexpected response and
|
|
8892
|
-
// fails loudly BEFORE anything is signed - never silently ignored.
|
|
8893
|
-
if ((curTx === null || curTx === void 0 ? void 0 : curTx.evmTransaction) != null) {
|
|
8894
|
-
throw new Error('Unsupported 202 transaction shape: the write response carried an evmTransaction, ' +
|
|
8895
|
-
'but EVM onchain writes are no longer supported. Nothing was signed or submitted.');
|
|
8896
|
-
}
|
|
8897
|
-
const hasSerializedSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.serializedTransaction) != null;
|
|
8898
|
-
const hasBuiltSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.transactionArgs) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.remainingAccounts) != null ||
|
|
8899
|
-
(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;
|
|
8900
|
-
if (hasSerializedSolanaTarget && hasBuiltSolanaTarget) {
|
|
8901
|
-
throw new Error('Ambiguous on-chain write response mixes Solana transaction target formats');
|
|
8902
|
-
}
|
|
8903
|
-
// All requested paths (writes AND deletes), in request order. Used for the
|
|
8904
|
-
// post-confirm mirror read-back, which correlates every requested path.
|
|
8905
|
-
// The pre-sign validation derives its own full expected intent from
|
|
8906
|
-
// `documents` (see below) and needs nothing from this list.
|
|
8907
|
-
const requestedPaths = documents.map(d => d.destinationPath);
|
|
8908
|
-
const requestedDocuments = buildRequestedDocuments(documents);
|
|
8909
|
-
const appId = config.appId;
|
|
8910
|
-
// The lane comes verbatim from the worker, and is read BEFORE anything is
|
|
8911
|
-
// signed or submitted: a missing tag fails closed while nothing has been
|
|
8912
|
-
// broadcast, instead of stranding a landed transaction with no receipt.
|
|
8913
|
-
const workerChain = readWorkerChainTag((_k = setResponse.data) === null || _k === void 0 ? void 0 : _k.receipt, setResponse.data, curTx);
|
|
8914
|
-
if (!workerChain) {
|
|
8915
|
-
throw new Error('The write response carried no execution-chain tag, so this receipt could not state where the write ran. ' +
|
|
8916
|
-
'Nothing was signed or submitted.');
|
|
8917
|
-
}
|
|
8918
|
-
if (workerChain === 'realtime_offchain') {
|
|
8919
|
-
// Poofnet: the wallet signs the worker's unsendable approval message and
|
|
8920
|
-
// the worker verifies and commits it. Nothing is submitted to any chain.
|
|
8921
|
-
if (typeof curTx.serializedTransaction !== 'string' || typeof curTx.poofnetIntentId !== 'string') {
|
|
8922
|
-
throw new Error('Unsupported 202 transaction shape: a poofnet write needs serializedTransaction and poofnetIntentId');
|
|
8911
|
+
// Until something is sent, every failure below is definitively not applied.
|
|
8912
|
+
let sending = false;
|
|
8913
|
+
try {
|
|
8914
|
+
const { transactions, offchainTransaction } = setResponse.data;
|
|
8915
|
+
// Handle offchain transaction flow (for 'offchain' protocol apps)
|
|
8916
|
+
if (offchainTransaction && Array.isArray(transactions) && transactions.length > 0) {
|
|
8917
|
+
throw new Error('Ambiguous write response mixes offchain and onchain transaction targets');
|
|
8923
8918
|
}
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
status: 'signed', appId, requestedDocuments: buildRequestedDocuments(documents),
|
|
8930
|
-
chain: 'realtime_offchain', transactionId: null, signedTransaction,
|
|
8931
|
-
poofnetIntentId: curTx.poofnetIntentId,
|
|
8932
|
-
};
|
|
8919
|
+
if (offchainTransaction) {
|
|
8920
|
+
// Offchain signing is retired: no server mints this envelope any more
|
|
8921
|
+
// (the realtime worker commits poofnet writes directly). Fail loudly
|
|
8922
|
+
// rather than silently ignoring a payload the caller was asked to sign.
|
|
8923
|
+
throw new Error('Unsupported 202 transaction shape: offchain signing is retired');
|
|
8933
8924
|
}
|
|
8934
|
-
|
|
8935
|
-
if (
|
|
8936
|
-
throw new Error(`
|
|
8925
|
+
// Handle Solana on-chain transaction flow
|
|
8926
|
+
if (!Array.isArray(transactions) || transactions.length !== 1) {
|
|
8927
|
+
throw new Error(`Expected exactly one on-chain transaction, received ${Array.isArray(transactions) ? transactions.length : 0}`);
|
|
8937
8928
|
}
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8929
|
+
const curTx = transactions[0];
|
|
8930
|
+
// The EVM onchain data plane is retired: no worker mints an EVM 202 any
|
|
8931
|
+
// more. A payload that still carries one is an unexpected response and
|
|
8932
|
+
// fails loudly BEFORE anything is signed - never silently ignored.
|
|
8933
|
+
if ((curTx === null || curTx === void 0 ? void 0 : curTx.evmTransaction) != null) {
|
|
8934
|
+
throw new Error('Unsupported 202 transaction shape: the write response carried an evmTransaction, ' +
|
|
8935
|
+
'but EVM onchain writes are no longer supported. Nothing was signed or submitted.');
|
|
8936
|
+
}
|
|
8937
|
+
const hasSerializedSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.serializedTransaction) != null;
|
|
8938
|
+
const hasBuiltSolanaTarget = (curTx === null || curTx === void 0 ? void 0 : curTx.transactionArgs) != null || (curTx === null || curTx === void 0 ? void 0 : curTx.remainingAccounts) != null ||
|
|
8939
|
+
(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;
|
|
8940
|
+
if (hasSerializedSolanaTarget && hasBuiltSolanaTarget) {
|
|
8941
|
+
throw new Error('Ambiguous on-chain write response mixes Solana transaction target formats');
|
|
8942
|
+
}
|
|
8943
|
+
// All requested paths (writes AND deletes), in request order. Used for the
|
|
8944
|
+
// post-confirm mirror read-back, which correlates every requested path.
|
|
8945
|
+
// The pre-sign validation derives its own full expected intent from
|
|
8946
|
+
// `documents` (see below) and needs nothing from this list.
|
|
8947
|
+
const requestedPaths = documents.map(d => d.destinationPath);
|
|
8948
|
+
const requestedDocuments = buildRequestedDocuments(documents);
|
|
8949
|
+
const appId = config.appId;
|
|
8950
|
+
// The lane comes verbatim from the worker, and is read BEFORE anything is
|
|
8951
|
+
// signed or submitted: a missing tag fails closed while nothing has been
|
|
8952
|
+
// broadcast, instead of stranding a landed transaction with no receipt.
|
|
8953
|
+
const workerChain = readWorkerChainTag((_k = setResponse.data) === null || _k === void 0 ? void 0 : _k.receipt, setResponse.data, curTx);
|
|
8954
|
+
if (!workerChain) {
|
|
8955
|
+
throw new Error('The write response carried no execution-chain tag, so this receipt could not state where the write ran. ' +
|
|
8943
8956
|
'Nothing was signed or submitted.');
|
|
8944
8957
|
}
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8958
|
+
if (workerChain === 'realtime_offchain') {
|
|
8959
|
+
// Poofnet: the wallet signs the worker's unsendable approval message and
|
|
8960
|
+
// the worker verifies and commits it. Nothing is submitted to any chain.
|
|
8961
|
+
if (typeof curTx.serializedTransaction !== 'string' || typeof curTx.poofnetIntentId !== 'string') {
|
|
8962
|
+
throw new Error('Unsupported 202 transaction shape: a poofnet write needs serializedTransaction and poofnetIntentId');
|
|
8963
|
+
}
|
|
8964
|
+
const { signPoofnetTransaction, buildExpectedWriteIntent } = await import('./solana-operations-Dtow91W5.mjs');
|
|
8965
|
+
const signedTransaction = await signPoofnetTransaction(curTx.serializedTransaction, authProvider, options, buildExpectedWriteIntent(documents));
|
|
8966
|
+
// Signing-only, exactly as on a real chain: signed and NOT committed.
|
|
8967
|
+
if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
|
|
8968
|
+
return {
|
|
8969
|
+
status: 'signed', appId, requestedDocuments: buildRequestedDocuments(documents),
|
|
8970
|
+
chain: 'realtime_offchain', transactionId: null, signedTransaction,
|
|
8971
|
+
poofnetIntentId: curTx.poofnetIntentId,
|
|
8972
|
+
};
|
|
8973
|
+
}
|
|
8974
|
+
// The commit PUT is the one ambiguous step of this lane: a lost response
|
|
8975
|
+
// may follow a commit, so its failures stay untagged (read the path back).
|
|
8976
|
+
sending = true;
|
|
8977
|
+
const commitResponse = await makeApiRequest('PUT', 'items/signed', { intentId: curTx.poofnetIntentId, signedTransaction }, options === null || options === void 0 ? void 0 : options._overrides);
|
|
8978
|
+
if (commitResponse.status !== 200) {
|
|
8979
|
+
throw new Error(`Poofnet signed write was not committed (status ${commitResponse.status})`);
|
|
8980
|
+
}
|
|
8981
|
+
return directCommitResult(commitResponse, documents);
|
|
8962
8982
|
}
|
|
8963
|
-
if (
|
|
8983
|
+
if (curTx.serializedTransaction) {
|
|
8984
|
+
if (!SOLANA_CHAIN_TAGS.has(workerChain)) {
|
|
8985
|
+
throw new Error(`The write response reported execution chain "${workerChain}" for a Solana transaction. ` +
|
|
8986
|
+
'Nothing was signed or submitted.');
|
|
8987
|
+
}
|
|
8988
|
+
const solanaChain = workerChain;
|
|
8989
|
+
const { handlePreBuiltTransaction, buildExpectedWriteIntent } = await import('./solana-operations-Dtow91W5.mjs');
|
|
8990
|
+
// OA-0001: derive the expected intent from OUR OWN request (the one
|
|
8991
|
+
// ground truth a tampered builder response cannot change) so the
|
|
8992
|
+
// validator can reject any transaction whose operation semantics
|
|
8993
|
+
// diverge from it BEFORE the wallet is asked to sign.
|
|
8994
|
+
const expectedIntent = buildExpectedWriteIntent(documents);
|
|
8995
|
+
const onBroadcast = options === null || options === void 0 ? void 0 : options.onBroadcast;
|
|
8996
|
+
const solanaOutcome = await handlePreBuiltTransaction(curTx, authProvider, options, expectedIntent, onBroadcast && (async (signed) => {
|
|
8997
|
+
await onBroadcast({
|
|
8998
|
+
status: 'submitted', appId, requestedDocuments, chain: solanaChain,
|
|
8999
|
+
transactionId: signed.transactionSignature,
|
|
9000
|
+
signedTransaction: signed.signedTransaction,
|
|
9001
|
+
fence: signed.fence,
|
|
9002
|
+
confirmation: { state: 'unknown', reason: 'about to broadcast' },
|
|
9003
|
+
});
|
|
9004
|
+
}));
|
|
9005
|
+
// Past this point the bytes may be on the network: nothing is tagged here.
|
|
9006
|
+
sending = true;
|
|
9007
|
+
// `shouldSubmitTx: false` signed WITHOUT sending — no signature exists,
|
|
9008
|
+
// and there is nothing to mirror, so no synchronization is attempted.
|
|
9009
|
+
if (solanaOutcome.outcome === 'signed') {
|
|
9010
|
+
return {
|
|
9011
|
+
status: 'signed', appId, requestedDocuments, chain: solanaChain,
|
|
9012
|
+
transactionId: null,
|
|
9013
|
+
signedTransaction: solanaOutcome.signedTransaction,
|
|
9014
|
+
fence: solanaOutcome.fence,
|
|
9015
|
+
};
|
|
9016
|
+
}
|
|
9017
|
+
if (solanaOutcome.outcome === 'submitted') {
|
|
9018
|
+
return {
|
|
9019
|
+
status: 'submitted', appId, requestedDocuments, chain: solanaChain,
|
|
9020
|
+
transactionId: solanaOutcome.transactionSignature,
|
|
9021
|
+
signedTransaction: solanaOutcome.signedTransaction,
|
|
9022
|
+
fence: solanaOutcome.fence,
|
|
9023
|
+
confirmation: { state: 'unknown', reason: solanaOutcome.reason },
|
|
9024
|
+
};
|
|
9025
|
+
}
|
|
9026
|
+
// Confirmed: the receipt is already complete, so the mirror read is a
|
|
9027
|
+
// best-effort enrichment reported in `mirrorSync`, never a rejection.
|
|
9028
|
+
const mirrorSync = await attemptMirrorSync(requestedPaths, options);
|
|
8964
9029
|
return {
|
|
8965
|
-
status: '
|
|
9030
|
+
status: 'confirmed', appId, requestedDocuments, chain: solanaChain,
|
|
8966
9031
|
transactionId: solanaOutcome.transactionSignature,
|
|
8967
9032
|
signedTransaction: solanaOutcome.signedTransaction,
|
|
8968
9033
|
fence: solanaOutcome.fence,
|
|
8969
|
-
|
|
9034
|
+
confirmationContextSlot: solanaOutcome.confirmationContextSlot,
|
|
9035
|
+
mirrorSync,
|
|
8970
9036
|
};
|
|
8971
9037
|
}
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
return {
|
|
8976
|
-
status: 'confirmed', appId, requestedDocuments, chain: solanaChain,
|
|
8977
|
-
transactionId: solanaOutcome.transactionSignature,
|
|
8978
|
-
signedTransaction: solanaOutcome.signedTransaction,
|
|
8979
|
-
fence: solanaOutcome.fence,
|
|
8980
|
-
confirmationContextSlot: solanaOutcome.confirmationContextSlot,
|
|
8981
|
-
mirrorSync,
|
|
8982
|
-
};
|
|
9038
|
+
else {
|
|
9039
|
+
throw new Error('Unsupported 202 transaction shape: expected serializedTransaction');
|
|
9040
|
+
}
|
|
8983
9041
|
}
|
|
8984
|
-
|
|
8985
|
-
|
|
9042
|
+
catch (error) {
|
|
9043
|
+
// The Solana lane tags its own broadcast and on-chain failures; anything
|
|
9044
|
+
// untagged from it, and every poofnet step before the commit PUT, failed
|
|
9045
|
+
// before a single byte was sent.
|
|
9046
|
+
throw sending ? error : markWriteNotApplied(error, 'before_broadcast');
|
|
8986
9047
|
}
|
|
8987
9048
|
}
|
|
8988
9049
|
else if (setResponse.status === 200) {
|
|
@@ -9003,6 +9064,8 @@ async function setMany(many, options) {
|
|
|
9003
9064
|
* of a result document (a delete returns the PREVIOUS document, so its stale
|
|
9004
9065
|
* `_transaction_hash` would misreport the delete).
|
|
9005
9066
|
*/
|
|
9067
|
+
/** HTTP statuses on the write request that prove the server refused it before anything happened. */
|
|
9068
|
+
const DEFINITIVE_WRITE_REFUSAL_STATUSES = new Set([400, 401, 402, 403, 404, 409, 422, 429]);
|
|
9006
9069
|
function directCommitResult(response, documents) {
|
|
9007
9070
|
var _a;
|
|
9008
9071
|
const body = (response.data && typeof response.data === 'object' && !Array.isArray(response.data))
|
|
@@ -9271,48 +9334,6 @@ var operations = /*#__PURE__*/Object.freeze({
|
|
|
9271
9334
|
syncItems: syncItems
|
|
9272
9335
|
});
|
|
9273
9336
|
|
|
9274
|
-
/** The highest Solana transaction version this SDK reads back (SIMD-0385 v1). */
|
|
9275
|
-
const SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION = 1;
|
|
9276
|
-
/**
|
|
9277
|
-
* getTransaction that survives a SIMD-0385 v1 response. @solana/web3.js 1.98.x
|
|
9278
|
-
* validates `version` against `0 | 'legacy'` and THROWS on 1 even when the request
|
|
9279
|
-
* raised the ceiling, so a real `Connection` (which exposes `rpcEndpoint`) is read
|
|
9280
|
-
* as raw JSON-RPC instead. An injected double without an endpoint goes through its
|
|
9281
|
-
* own `getTransaction` with the ceiling raised. Returns the RPC `result` (null when
|
|
9282
|
-
* the signature is unknown); RPC and transport failures throw so callers keep
|
|
9283
|
-
* treating a failed lookup as inconclusive rather than as absence.
|
|
9284
|
-
*/
|
|
9285
|
-
async function getTransactionJson(rpc, signature, commitment = 'confirmed') {
|
|
9286
|
-
var _a;
|
|
9287
|
-
const endpoint = typeof (rpc === null || rpc === void 0 ? void 0 : rpc.rpcEndpoint) === 'string' ? rpc.rpcEndpoint.trim() : '';
|
|
9288
|
-
if (!endpoint) {
|
|
9289
|
-
return rpc.getTransaction(signature, {
|
|
9290
|
-
maxSupportedTransactionVersion: SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION,
|
|
9291
|
-
commitment,
|
|
9292
|
-
});
|
|
9293
|
-
}
|
|
9294
|
-
const response = await fetch(endpoint, {
|
|
9295
|
-
method: 'POST',
|
|
9296
|
-
headers: { 'content-type': 'application/json' },
|
|
9297
|
-
body: JSON.stringify({
|
|
9298
|
-
jsonrpc: '2.0',
|
|
9299
|
-
id: 1,
|
|
9300
|
-
method: 'getTransaction',
|
|
9301
|
-
params: [signature, {
|
|
9302
|
-
commitment,
|
|
9303
|
-
encoding: 'json',
|
|
9304
|
-
maxSupportedTransactionVersion: SOLANA_MAX_SUPPORTED_TRANSACTION_VERSION,
|
|
9305
|
-
}],
|
|
9306
|
-
}),
|
|
9307
|
-
});
|
|
9308
|
-
if (!response.ok)
|
|
9309
|
-
throw new Error(`getTransaction http ${response.status}`);
|
|
9310
|
-
const body = await response.json();
|
|
9311
|
-
if (body === null || body === void 0 ? void 0 : body.error)
|
|
9312
|
-
throw new Error(`getTransaction rpc error ${body.error.code}: ${body.error.message}`);
|
|
9313
|
-
return (_a = body === null || body === void 0 ? void 0 : body.result) !== null && _a !== void 0 ? _a : null;
|
|
9314
|
-
}
|
|
9315
|
-
|
|
9316
9337
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
9317
9338
|
const DEFAULT_MAX_ATTEMPTS$1 = 20;
|
|
9318
9339
|
const DEFAULT_POLL_INTERVAL_MS = 3000;
|
|
@@ -9386,20 +9407,50 @@ async function resolveSolanaRpc(config, options) {
|
|
|
9386
9407
|
return new Connection(rpcUrl, 'confirmed');
|
|
9387
9408
|
}
|
|
9388
9409
|
/**
|
|
9389
|
-
*
|
|
9390
|
-
*
|
|
9391
|
-
*
|
|
9410
|
+
* Whether a signature status is final enough to decide on. `processed` can still belong to a fork
|
|
9411
|
+
* that is dropped, so only `confirmed` or `finalized` settle a write; an RPC that omits
|
|
9412
|
+
* `confirmationStatus` reports a rooted transaction as `confirmations: null`.
|
|
9413
|
+
*/
|
|
9414
|
+
function settledStatus(status) {
|
|
9415
|
+
if (!status)
|
|
9416
|
+
return false;
|
|
9417
|
+
if (status.confirmationStatus === 'confirmed' || status.confirmationStatus === 'finalized')
|
|
9418
|
+
return true;
|
|
9419
|
+
return status.confirmationStatus == null && status.confirmations === null;
|
|
9420
|
+
}
|
|
9421
|
+
/**
|
|
9422
|
+
* Solana reconciliation NEVER broadcasts. It settles on a `confirmed` or `finalized` status only,
|
|
9423
|
+
* and reaches `expired_not_landed` only from the chain's own blockhash expiry: the FINALIZED block
|
|
9424
|
+
* height is past the fence, so the network can never accept these bytes again, and a
|
|
9425
|
+
* history-searching status lookup from a node that has seen that finalized slot finds no record.
|
|
9426
|
+
* Anything short of that - a `processed` status, a lookup that fails, a node behind the expiry
|
|
9427
|
+
* point - stays `submitted`.
|
|
9392
9428
|
*/
|
|
9393
9429
|
async function reconcileSolana(receipt, config, options) {
|
|
9394
9430
|
var _a, _b, _c, _d;
|
|
9395
9431
|
const rpc = await resolveSolanaRpc(config, options);
|
|
9432
|
+
if (typeof rpc.getSignatureStatuses !== 'function') {
|
|
9433
|
+
return stillSubmitted(receipt, 'the configured Solana RPC cannot report signature statuses');
|
|
9434
|
+
}
|
|
9435
|
+
// Expiry is read BEFORE the status, so an absence observed afterwards is an absence after the
|
|
9436
|
+
// fence closed for good. A finalized height past lastValidBlockHeight is final: the blockhash
|
|
9437
|
+
// can never become valid again.
|
|
9438
|
+
let finalizedHeight;
|
|
9439
|
+
let finalizedSlot;
|
|
9440
|
+
try {
|
|
9441
|
+
if (typeof rpc.getBlockHeight === 'function')
|
|
9442
|
+
finalizedHeight = await rpc.getBlockHeight('finalized');
|
|
9443
|
+
if (typeof rpc.getSlot === 'function')
|
|
9444
|
+
finalizedSlot = await rpc.getSlot('finalized');
|
|
9445
|
+
}
|
|
9446
|
+
catch (error) {
|
|
9447
|
+
return stillSubmitted(receipt, `finalized height lookup failed: ${errorText(error)}`);
|
|
9448
|
+
}
|
|
9449
|
+
const expired = typeof finalizedHeight === 'number' && finalizedHeight > receipt.fence.lastValidBlockHeight;
|
|
9396
9450
|
let statusValue = null;
|
|
9397
9451
|
let contextSlot;
|
|
9398
9452
|
try {
|
|
9399
|
-
|
|
9400
|
-
return stillSubmitted(receipt, 'the configured Solana RPC cannot report signature statuses');
|
|
9401
|
-
}
|
|
9402
|
-
const statuses = await rpc.getSignatureStatuses([receipt.transactionId]);
|
|
9453
|
+
const statuses = await rpc.getSignatureStatuses([receipt.transactionId], { searchTransactionHistory: true });
|
|
9403
9454
|
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;
|
|
9404
9455
|
contextSlot = (_c = statuses === null || statuses === void 0 ? void 0 : statuses.context) === null || _c === void 0 ? void 0 : _c.slot;
|
|
9405
9456
|
}
|
|
@@ -9407,9 +9458,12 @@ async function reconcileSolana(receipt, config, options) {
|
|
|
9407
9458
|
return stillSubmitted(receipt, `signature status lookup failed: ${errorText(error)}`);
|
|
9408
9459
|
}
|
|
9409
9460
|
if (statusValue) {
|
|
9461
|
+
if (!settledStatus(statusValue)) {
|
|
9462
|
+
return stillSubmitted(receipt, `seen at ${String((_d = statusValue.confirmationStatus) !== null && _d !== void 0 ? _d : 'an unconfirmed')} commitment; waiting for confirmed`);
|
|
9463
|
+
}
|
|
9410
9464
|
// Landed. A landed-but-failed transaction is a genuine failure, not `submitted`.
|
|
9411
9465
|
if (statusValue.err) {
|
|
9412
|
-
throw new Error(`Transaction failed: ${JSON.stringify(statusValue.err)}`);
|
|
9466
|
+
throw markWriteNotApplied(new Error(`Transaction failed: ${JSON.stringify(statusValue.err)}`), 'failed_onchain');
|
|
9413
9467
|
}
|
|
9414
9468
|
const confirmed = {
|
|
9415
9469
|
status: 'confirmed',
|
|
@@ -9419,50 +9473,21 @@ async function reconcileSolana(receipt, config, options) {
|
|
|
9419
9473
|
transactionId: receipt.transactionId,
|
|
9420
9474
|
signedTransaction: receipt.signedTransaction,
|
|
9421
9475
|
fence: receipt.fence,
|
|
9422
|
-
confirmationContextSlot: contextSlot !== null && contextSlot !== void 0 ? contextSlot : 0,
|
|
9476
|
+
confirmationContextSlot: typeof statusValue.slot === 'number' ? statusValue.slot : (contextSlot !== null && contextSlot !== void 0 ? contextSlot : 0),
|
|
9423
9477
|
mirrorSync: await mirrorFor(receipt, options),
|
|
9424
9478
|
};
|
|
9425
9479
|
return confirmed;
|
|
9426
9480
|
}
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
let blockHeight;
|
|
9430
|
-
try {
|
|
9431
|
-
blockHeight = typeof rpc.getBlockHeight === 'function' ? await rpc.getBlockHeight('confirmed') : undefined;
|
|
9481
|
+
if (typeof finalizedHeight !== 'number') {
|
|
9482
|
+
return stillSubmitted(receipt, 'expiry could not be observed: the RPC reported no finalized block height');
|
|
9432
9483
|
}
|
|
9433
|
-
|
|
9434
|
-
return stillSubmitted(receipt, `block height
|
|
9435
|
-
}
|
|
9436
|
-
if (typeof blockHeight !== 'number') {
|
|
9437
|
-
return stillSubmitted(receipt, 'expiry could not be observed: the RPC reported no block height');
|
|
9438
|
-
}
|
|
9439
|
-
if (blockHeight <= receipt.fence.lastValidBlockHeight) {
|
|
9440
|
-
return stillSubmitted(receipt, `not yet expired: block height ${blockHeight} is within the fence (lastValidBlockHeight ${receipt.fence.lastValidBlockHeight})`);
|
|
9441
|
-
}
|
|
9442
|
-
// Expired. Prove absence from history before declaring the write retry-safe.
|
|
9443
|
-
let history;
|
|
9444
|
-
try {
|
|
9445
|
-
history = await getTransactionJson(rpc, receipt.transactionId, 'confirmed');
|
|
9484
|
+
if (!expired) {
|
|
9485
|
+
return stillSubmitted(receipt, `not yet expired: finalized block height ${finalizedHeight} is within the fence (lastValidBlockHeight ${receipt.fence.lastValidBlockHeight})`);
|
|
9446
9486
|
}
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
if ((_d = history === null || history === void 0 ? void 0 : history.meta) === null || _d === void 0 ? void 0 : _d.err) {
|
|
9452
|
-
throw new Error(`Transaction failed: ${JSON.stringify(history.meta.err)}`);
|
|
9453
|
-
}
|
|
9454
|
-
const confirmed = {
|
|
9455
|
-
status: 'confirmed',
|
|
9456
|
-
appId: receipt.appId,
|
|
9457
|
-
requestedDocuments: receipt.requestedDocuments,
|
|
9458
|
-
chain: receipt.chain,
|
|
9459
|
-
transactionId: receipt.transactionId,
|
|
9460
|
-
signedTransaction: receipt.signedTransaction,
|
|
9461
|
-
fence: receipt.fence,
|
|
9462
|
-
confirmationContextSlot: typeof history.slot === 'number' ? history.slot : (contextSlot !== null && contextSlot !== void 0 ? contextSlot : 0),
|
|
9463
|
-
mirrorSync: await mirrorFor(receipt, options),
|
|
9464
|
-
};
|
|
9465
|
-
return confirmed;
|
|
9487
|
+
// A load-balanced RPC may answer the status from a node behind the one that reported the
|
|
9488
|
+
// finalized height. Its absence proves nothing until that node has seen the finalized slot.
|
|
9489
|
+
if (typeof finalizedSlot !== 'number' || typeof contextSlot !== 'number' || contextSlot < finalizedSlot) {
|
|
9490
|
+
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'}`);
|
|
9466
9491
|
}
|
|
9467
9492
|
return {
|
|
9468
9493
|
status: 'expired_not_landed',
|
|
@@ -10725,7 +10750,7 @@ function toMillis(seconds) {
|
|
|
10725
10750
|
|
|
10726
10751
|
/** SIWS message creation is async already, so its onchain module can be lazy. */
|
|
10727
10752
|
async function genSolanaMessage(address, nonce) {
|
|
10728
|
-
const implementation = await import('./solana-message-
|
|
10753
|
+
const implementation = await import('./solana-message-BBKdydqt.mjs');
|
|
10729
10754
|
return implementation.genSolanaMessage(address, nonce);
|
|
10730
10755
|
}
|
|
10731
10756
|
|
|
@@ -11274,5 +11299,5 @@ function defineLiveModule(mod) {
|
|
|
11274
11299
|
return mod;
|
|
11275
11300
|
}
|
|
11276
11301
|
|
|
11277
|
-
export {
|
|
11278
|
-
//# sourceMappingURL=index-
|
|
11302
|
+
export { increment as $, isWriteNotApplied as A, writeNotAppliedPhase as B, subscribe as C, closeAllSubscriptions as D, clearCache as E, getCachedData as F, reconnectWithNewAuth as G, createClient as H, InsufficientBalanceError as I, exchangeAppToken as J, clearAppTokenCache as K, createAppTokenAuthHeaders as L, AppTokenExchangeError as M, subscribeQuery as N, closeAllQuerySubscriptions as O, canonicalizeArgs as P, canonicalizeResult as Q, DEFAULT_QUERY_POLL_INTERVAL_MS as R, ScopedClientReadOnlyError as S, MIN_QUERY_POLL_INTERVAL_MS as T, BoundedDeclineError as U, deriveDecline as V, dispatchDeclineEvent as W, DECLINE_EVENT_NAME as X, dispatchRateLimitEvent as Y, RATE_LIMIT_EVENT_NAME as Z, hasActiveConnection as _, getWebhookKeysUrl as a, serverTimestamp as a0, now as a1, toSeconds as a2, toMillis as a3, getIdToken as a4, deriveUserIdentityFromIdToken as a5, getSessionGeneration as a6, WebSessionManager as a7, ReactNativeSessionManager as a8, getActiveSessionManager as a9, live as aA, intent as aB, status as aC, subscribeView as aD, LiveIntentError as aE, withEffects as aF, isEffectResult as aG, defineLiveModule as aH, EFFECT_INTENT_ADDRESS as aI, onSessionCleared as aa, SessionEnvironmentError as ab, UNSUPPORTED_ENVIRONMENT_CODE as ac, AUTH_CHANGED_CODE as ad, AUTH_EXPIRED_CODE as ae, isAuthExpiredError as af, getFreshAuthToken as ag, ServerSessionManager as ah, createSessionWithSignature as ai, refreshSession as aj, revokeSession as ak, signSessionCreateMessage as al, genAuthNonce as am, genSolanaMessage as an, createSolanaSignInRequest as ao, createSolanaSignInMessageText as ap, genSolanaSignInRequest as aq, genSolanaSignInMessage as ar, browserSignInDomain as as, SOLANA_SIGN_IN_STATEMENT as at, genSiweMessage as au, normalizeEvmAddress as av, toLowerEvmAddress as aw, functions as ax, invoke as ay, FunctionInvokeError as az, bufferExports as b, getConfiguredAppId as c, get as d, getMany as e, docId as f, getConfig as g, setMany as h, init as i, setFile as j, getFiles as k, search as l, markWriteNotApplied as m, runQueryMany as n, runExpression as o, runExpressionMany as p, queryAggregate as q, runQuery as r, set as s, signMessage as t, signTransaction as u, signAndSubmitTransaction as v, count as w, aggregate as x, reconcileSetResult as y, waitForSetResult as z };
|
|
11303
|
+
//# sourceMappingURL=index-No5Vz0YM.mjs.map
|