@metamask-previews/transaction-pay-controller 23.16.1-preview-9298fa429 → 23.16.1-preview-574b60e35
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/CHANGELOG.md +8 -0
- package/dist/strategy/fiat/chomp.cjs +58 -0
- package/dist/strategy/fiat/chomp.cjs.map +1 -0
- package/dist/strategy/fiat/chomp.d.cts +9 -0
- package/dist/strategy/fiat/chomp.d.cts.map +1 -0
- package/dist/strategy/fiat/chomp.d.mts +9 -0
- package/dist/strategy/fiat/chomp.d.mts.map +1 -0
- package/dist/strategy/fiat/chomp.mjs +54 -0
- package/dist/strategy/fiat/chomp.mjs.map +1 -0
- package/dist/strategy/fiat/fiat-direct-musd.cjs +50 -3
- package/dist/strategy/fiat/fiat-direct-musd.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.d.cts +7 -2
- package/dist/strategy/fiat/fiat-direct-musd.d.cts.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.d.mts +7 -2
- package/dist/strategy/fiat/fiat-direct-musd.d.mts.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.mjs +50 -3
- package/dist/strategy/fiat/fiat-direct-musd.mjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit.cjs +29 -3
- package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
- package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
- package/dist/strategy/fiat/fiat-submit.mjs +29 -3
- package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
- package/dist/strategy/fiat/utils.cjs +9 -4
- package/dist/strategy/fiat/utils.cjs.map +1 -1
- package/dist/strategy/fiat/utils.d.cts +20 -2
- package/dist/strategy/fiat/utils.d.cts.map +1 -1
- package/dist/strategy/fiat/utils.d.mts +20 -2
- package/dist/strategy/fiat/utils.d.mts.map +1 -1
- package/dist/strategy/fiat/utils.mjs +9 -4
- package/dist/strategy/fiat/utils.mjs.map +1 -1
- package/dist/tests/messenger-mock.d.cts +1 -1
- package/dist/tests/messenger-mock.d.mts +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +2 -2
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/transaction.cjs +11 -8
- package/dist/utils/transaction.cjs.map +1 -1
- package/dist/utils/transaction.d.cts +16 -4
- package/dist/utils/transaction.d.cts.map +1 -1
- package/dist/utils/transaction.d.mts +16 -4
- package/dist/utils/transaction.d.mts.map +1 -1
- package/dist/utils/transaction.mjs +11 -8
- package/dist/utils/transaction.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Add CHOMP idempotency for direct mUSD vault deposits ([#9267](https://github.com/MetaMask/core/pull/9267))
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Wait for keyring unlock before executing fiat post-ramp second leg ([#9267](https://github.com/MetaMask/core/pull/9267))
|
|
17
|
+
|
|
10
18
|
## [23.16.1]
|
|
11
19
|
|
|
12
20
|
### Changed
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findRecentChompVaultDeposit = void 0;
|
|
4
|
+
const utils_1 = require("@metamask/utils");
|
|
5
|
+
const constants_1 = require("../../constants.cjs");
|
|
6
|
+
const logger_1 = require("../../logger.cjs");
|
|
7
|
+
const provider_1 = require("../../utils/provider.cjs");
|
|
8
|
+
const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'chomp');
|
|
9
|
+
/** keccak256('Transfer(address,address,uint256)') */
|
|
10
|
+
const ERC20_TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
|
11
|
+
async function findRecentChompVaultDeposit({ messenger, moneyAccountAddress, sourceAmountRaw, fromBlock, }) {
|
|
12
|
+
const fromPadded = padAddress(moneyAccountAddress);
|
|
13
|
+
const logs = await (0, provider_1.rpcRequest)({
|
|
14
|
+
messenger,
|
|
15
|
+
chainId: constants_1.CHAIN_ID_MONAD,
|
|
16
|
+
method: 'eth_getLogs',
|
|
17
|
+
params: [
|
|
18
|
+
{
|
|
19
|
+
address: constants_1.MUSD_MONAD_ADDRESS,
|
|
20
|
+
fromBlock,
|
|
21
|
+
toBlock: 'latest',
|
|
22
|
+
topics: [ERC20_TRANSFER_TOPIC, fromPadded, null],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
log('CHOMP scan: mUSD Transfer logs found', {
|
|
27
|
+
count: logs.length,
|
|
28
|
+
fromBlock,
|
|
29
|
+
moneyAccountAddress,
|
|
30
|
+
});
|
|
31
|
+
const requiredAmount = BigInt(sourceAmountRaw);
|
|
32
|
+
// Examine newest logs first so we return the most recent CHOMP match.
|
|
33
|
+
for (const txLog of [...logs].reverse()) {
|
|
34
|
+
const transferAmount = BigInt(txLog.data === '0x' ? '0x0' : txLog.data);
|
|
35
|
+
if (transferAmount < requiredAmount) {
|
|
36
|
+
log('CHOMP scan: skipping log — transfer amount below required', {
|
|
37
|
+
requiredAmount: requiredAmount.toString(),
|
|
38
|
+
transferAmount: transferAmount.toString(),
|
|
39
|
+
txHash: txLog.transactionHash,
|
|
40
|
+
});
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
log('CHOMP scan: match found', {
|
|
44
|
+
moneyAccountAddress,
|
|
45
|
+
sourceAmountRaw,
|
|
46
|
+
transferAmount: transferAmount.toString(),
|
|
47
|
+
txHash: txLog.transactionHash,
|
|
48
|
+
});
|
|
49
|
+
return txLog.transactionHash;
|
|
50
|
+
}
|
|
51
|
+
log('CHOMP scan: no match found', { fromBlock, moneyAccountAddress });
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
exports.findRecentChompVaultDeposit = findRecentChompVaultDeposit;
|
|
55
|
+
function padAddress(address) {
|
|
56
|
+
return `0x${address.replace(/^0x/u, '').toLowerCase().padStart(64, '0')}`;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=chomp.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chomp.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/chomp.ts"],"names":[],"mappings":";;;AACA,2CAAqD;AAErD,mDAAqE;AACrE,6CAA6C;AAE7C,uDAAkD;AAElD,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,OAAO,CAAC,CAAC;AAEvD,qDAAqD;AACrD,MAAM,oBAAoB,GACxB,oEAAoE,CAAC;AAShE,KAAK,UAAU,2BAA2B,CAAC,EAChD,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,SAAS,GAMV;IACC,MAAM,UAAU,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAU,EAAW;QACtC,SAAS;QACT,OAAO,EAAE,0BAAc;QACvB,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE;YACN;gBACE,OAAO,EAAE,8BAAkB;gBAC3B,SAAS;gBACT,OAAO,EAAE,QAAQ;gBACjB,MAAM,EAAE,CAAC,oBAAoB,EAAE,UAAU,EAAE,IAAI,CAAC;aACjD;SACF;KACF,CAAC,CAAC;IAEH,GAAG,CAAC,sCAAsC,EAAE;QAC1C,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,SAAS;QACT,mBAAmB;KACpB,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;IAE/C,sEAAsE;IACtE,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QACxC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExE,IAAI,cAAc,GAAG,cAAc,EAAE,CAAC;YACpC,GAAG,CAAC,2DAA2D,EAAE;gBAC/D,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;gBACzC,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;gBACzC,MAAM,EAAE,KAAK,CAAC,eAAe;aAC9B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,GAAG,CAAC,yBAAyB,EAAE;YAC7B,mBAAmB;YACnB,eAAe;YACf,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;YACzC,MAAM,EAAE,KAAK,CAAC,eAAe;SAC9B,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,eAAe,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACtE,OAAO,SAAS,CAAC;AACnB,CAAC;AA5DD,kEA4DC;AAED,SAAS,UAAU,CAAC,OAAY;IAC9B,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5E,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { CHAIN_ID_MONAD, MUSD_MONAD_ADDRESS } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { rpcRequest } from '../../utils/provider';\n\nconst log = createModuleLogger(projectLogger, 'chomp');\n\n/** keccak256('Transfer(address,address,uint256)') */\nconst ERC20_TRANSFER_TOPIC =\n '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n\ntype RpcLog = {\n address: string;\n topics: string[];\n data: string;\n transactionHash: Hex;\n};\n\nexport async function findRecentChompVaultDeposit({\n messenger,\n moneyAccountAddress,\n sourceAmountRaw,\n fromBlock,\n}: {\n messenger: TransactionPayControllerMessenger;\n moneyAccountAddress: Hex;\n sourceAmountRaw: string;\n fromBlock: Hex;\n}): Promise<Hex | undefined> {\n const fromPadded = padAddress(moneyAccountAddress);\n\n const logs = await rpcRequest<RpcLog[]>({\n messenger,\n chainId: CHAIN_ID_MONAD,\n method: 'eth_getLogs',\n params: [\n {\n address: MUSD_MONAD_ADDRESS,\n fromBlock,\n toBlock: 'latest',\n topics: [ERC20_TRANSFER_TOPIC, fromPadded, null],\n },\n ],\n });\n\n log('CHOMP scan: mUSD Transfer logs found', {\n count: logs.length,\n fromBlock,\n moneyAccountAddress,\n });\n\n const requiredAmount = BigInt(sourceAmountRaw);\n\n // Examine newest logs first so we return the most recent CHOMP match.\n for (const txLog of [...logs].reverse()) {\n const transferAmount = BigInt(txLog.data === '0x' ? '0x0' : txLog.data);\n\n if (transferAmount < requiredAmount) {\n log('CHOMP scan: skipping log — transfer amount below required', {\n requiredAmount: requiredAmount.toString(),\n transferAmount: transferAmount.toString(),\n txHash: txLog.transactionHash,\n });\n continue;\n }\n\n log('CHOMP scan: match found', {\n moneyAccountAddress,\n sourceAmountRaw,\n transferAmount: transferAmount.toString(),\n txHash: txLog.transactionHash,\n });\n\n return txLog.transactionHash;\n }\n\n log('CHOMP scan: no match found', { fromBlock, moneyAccountAddress });\n return undefined;\n}\n\nfunction padAddress(address: Hex): string {\n return `0x${address.replace(/^0x/u, '').toLowerCase().padStart(64, '0')}`;\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Hex } from "@metamask/utils";
|
|
2
|
+
import type { TransactionPayControllerMessenger } from "../../types.cjs";
|
|
3
|
+
export declare function findRecentChompVaultDeposit({ messenger, moneyAccountAddress, sourceAmountRaw, fromBlock, }: {
|
|
4
|
+
messenger: TransactionPayControllerMessenger;
|
|
5
|
+
moneyAccountAddress: Hex;
|
|
6
|
+
sourceAmountRaw: string;
|
|
7
|
+
fromBlock: Hex;
|
|
8
|
+
}): Promise<Hex | undefined>;
|
|
9
|
+
//# sourceMappingURL=chomp.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chomp.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/chomp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAgBrE,wBAAsB,2BAA2B,CAAC,EAChD,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,SAAS,GACV,EAAE;IACD,SAAS,EAAE,iCAAiC,CAAC;IAC7C,mBAAmB,EAAE,GAAG,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,GAAG,CAAC;CAChB,GAAG,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC,CAkD3B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Hex } from "@metamask/utils";
|
|
2
|
+
import type { TransactionPayControllerMessenger } from "../../types.mjs";
|
|
3
|
+
export declare function findRecentChompVaultDeposit({ messenger, moneyAccountAddress, sourceAmountRaw, fromBlock, }: {
|
|
4
|
+
messenger: TransactionPayControllerMessenger;
|
|
5
|
+
moneyAccountAddress: Hex;
|
|
6
|
+
sourceAmountRaw: string;
|
|
7
|
+
fromBlock: Hex;
|
|
8
|
+
}): Promise<Hex | undefined>;
|
|
9
|
+
//# sourceMappingURL=chomp.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chomp.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/chomp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAgBrE,wBAAsB,2BAA2B,CAAC,EAChD,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,SAAS,GACV,EAAE;IACD,SAAS,EAAE,iCAAiC,CAAC;IAC7C,mBAAmB,EAAE,GAAG,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,GAAG,CAAC;CAChB,GAAG,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC,CAkD3B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createModuleLogger } from "@metamask/utils";
|
|
2
|
+
import { CHAIN_ID_MONAD, MUSD_MONAD_ADDRESS } from "../../constants.mjs";
|
|
3
|
+
import { projectLogger } from "../../logger.mjs";
|
|
4
|
+
import { rpcRequest } from "../../utils/provider.mjs";
|
|
5
|
+
const log = createModuleLogger(projectLogger, 'chomp');
|
|
6
|
+
/** keccak256('Transfer(address,address,uint256)') */
|
|
7
|
+
const ERC20_TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
|
8
|
+
export async function findRecentChompVaultDeposit({ messenger, moneyAccountAddress, sourceAmountRaw, fromBlock, }) {
|
|
9
|
+
const fromPadded = padAddress(moneyAccountAddress);
|
|
10
|
+
const logs = await rpcRequest({
|
|
11
|
+
messenger,
|
|
12
|
+
chainId: CHAIN_ID_MONAD,
|
|
13
|
+
method: 'eth_getLogs',
|
|
14
|
+
params: [
|
|
15
|
+
{
|
|
16
|
+
address: MUSD_MONAD_ADDRESS,
|
|
17
|
+
fromBlock,
|
|
18
|
+
toBlock: 'latest',
|
|
19
|
+
topics: [ERC20_TRANSFER_TOPIC, fromPadded, null],
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
});
|
|
23
|
+
log('CHOMP scan: mUSD Transfer logs found', {
|
|
24
|
+
count: logs.length,
|
|
25
|
+
fromBlock,
|
|
26
|
+
moneyAccountAddress,
|
|
27
|
+
});
|
|
28
|
+
const requiredAmount = BigInt(sourceAmountRaw);
|
|
29
|
+
// Examine newest logs first so we return the most recent CHOMP match.
|
|
30
|
+
for (const txLog of [...logs].reverse()) {
|
|
31
|
+
const transferAmount = BigInt(txLog.data === '0x' ? '0x0' : txLog.data);
|
|
32
|
+
if (transferAmount < requiredAmount) {
|
|
33
|
+
log('CHOMP scan: skipping log — transfer amount below required', {
|
|
34
|
+
requiredAmount: requiredAmount.toString(),
|
|
35
|
+
transferAmount: transferAmount.toString(),
|
|
36
|
+
txHash: txLog.transactionHash,
|
|
37
|
+
});
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
log('CHOMP scan: match found', {
|
|
41
|
+
moneyAccountAddress,
|
|
42
|
+
sourceAmountRaw,
|
|
43
|
+
transferAmount: transferAmount.toString(),
|
|
44
|
+
txHash: txLog.transactionHash,
|
|
45
|
+
});
|
|
46
|
+
return txLog.transactionHash;
|
|
47
|
+
}
|
|
48
|
+
log('CHOMP scan: no match found', { fromBlock, moneyAccountAddress });
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
function padAddress(address) {
|
|
52
|
+
return `0x${address.replace(/^0x/u, '').toLowerCase().padStart(64, '0')}`;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=chomp.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chomp.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/chomp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AAErD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,4BAAwB;AACrE,OAAO,EAAE,aAAa,EAAE,yBAAqB;AAE7C,OAAO,EAAE,UAAU,EAAE,iCAA6B;AAElD,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAEvD,qDAAqD;AACrD,MAAM,oBAAoB,GACxB,oEAAoE,CAAC;AASvE,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,EAChD,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,SAAS,GAMV;IACC,MAAM,UAAU,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAW;QACtC,SAAS;QACT,OAAO,EAAE,cAAc;QACvB,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE;YACN;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,SAAS;gBACT,OAAO,EAAE,QAAQ;gBACjB,MAAM,EAAE,CAAC,oBAAoB,EAAE,UAAU,EAAE,IAAI,CAAC;aACjD;SACF;KACF,CAAC,CAAC;IAEH,GAAG,CAAC,sCAAsC,EAAE;QAC1C,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,SAAS;QACT,mBAAmB;KACpB,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;IAE/C,sEAAsE;IACtE,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QACxC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExE,IAAI,cAAc,GAAG,cAAc,EAAE,CAAC;YACpC,GAAG,CAAC,2DAA2D,EAAE;gBAC/D,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;gBACzC,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;gBACzC,MAAM,EAAE,KAAK,CAAC,eAAe;aAC9B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,GAAG,CAAC,yBAAyB,EAAE;YAC7B,mBAAmB;YACnB,eAAe;YACf,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;YACzC,MAAM,EAAE,KAAK,CAAC,eAAe;SAC9B,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,eAAe,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACtE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,OAAY;IAC9B,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5E,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { CHAIN_ID_MONAD, MUSD_MONAD_ADDRESS } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { rpcRequest } from '../../utils/provider';\n\nconst log = createModuleLogger(projectLogger, 'chomp');\n\n/** keccak256('Transfer(address,address,uint256)') */\nconst ERC20_TRANSFER_TOPIC =\n '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n\ntype RpcLog = {\n address: string;\n topics: string[];\n data: string;\n transactionHash: Hex;\n};\n\nexport async function findRecentChompVaultDeposit({\n messenger,\n moneyAccountAddress,\n sourceAmountRaw,\n fromBlock,\n}: {\n messenger: TransactionPayControllerMessenger;\n moneyAccountAddress: Hex;\n sourceAmountRaw: string;\n fromBlock: Hex;\n}): Promise<Hex | undefined> {\n const fromPadded = padAddress(moneyAccountAddress);\n\n const logs = await rpcRequest<RpcLog[]>({\n messenger,\n chainId: CHAIN_ID_MONAD,\n method: 'eth_getLogs',\n params: [\n {\n address: MUSD_MONAD_ADDRESS,\n fromBlock,\n toBlock: 'latest',\n topics: [ERC20_TRANSFER_TOPIC, fromPadded, null],\n },\n ],\n });\n\n log('CHOMP scan: mUSD Transfer logs found', {\n count: logs.length,\n fromBlock,\n moneyAccountAddress,\n });\n\n const requiredAmount = BigInt(sourceAmountRaw);\n\n // Examine newest logs first so we return the most recent CHOMP match.\n for (const txLog of [...logs].reverse()) {\n const transferAmount = BigInt(txLog.data === '0x' ? '0x0' : txLog.data);\n\n if (transferAmount < requiredAmount) {\n log('CHOMP scan: skipping log — transfer amount below required', {\n requiredAmount: requiredAmount.toString(),\n transferAmount: transferAmount.toString(),\n txHash: txLog.transactionHash,\n });\n continue;\n }\n\n log('CHOMP scan: match found', {\n moneyAccountAddress,\n sourceAmountRaw,\n transferAmount: transferAmount.toString(),\n txHash: txLog.transactionHash,\n });\n\n return txLog.transactionHash;\n }\n\n log('CHOMP scan: no match found', { fromBlock, moneyAccountAddress });\n return undefined;\n}\n\nfunction padAddress(address: Hex): string {\n return `0x${address.replace(/^0x/u, '').toLowerCase().padStart(64, '0')}`;\n}\n"]}
|
|
@@ -12,6 +12,7 @@ const feature_flags_1 = require("../../utils/feature-flags.cjs");
|
|
|
12
12
|
const provider_1 = require("../../utils/provider.cjs");
|
|
13
13
|
const token_1 = require("../../utils/token.cjs");
|
|
14
14
|
const transaction_1 = require("../../utils/transaction.cjs");
|
|
15
|
+
const chomp_1 = require("./chomp.cjs");
|
|
15
16
|
const constants_2 = require("./constants.cjs");
|
|
16
17
|
const utils_2 = require("./utils.cjs");
|
|
17
18
|
const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'fiat-direct-musd');
|
|
@@ -95,13 +96,14 @@ async function submitDirectMusdAfterFiatCompletion({ order, request, }) {
|
|
|
95
96
|
orderCrypto: order.cryptoCurrency,
|
|
96
97
|
transactionId: transaction.id,
|
|
97
98
|
});
|
|
98
|
-
const sourceAmountRaw = await (0, utils_2.resolveSourceAmountRaw)({
|
|
99
|
+
const { amountRaw: sourceAmountRaw, fromBlock } = await (0, utils_2.resolveSourceAmountRaw)({
|
|
99
100
|
messenger,
|
|
100
101
|
order,
|
|
101
102
|
fiatAsset: constants_2.MUSD_MONAD_FIAT_ASSET,
|
|
102
103
|
walletAddress: transaction.txParams.from,
|
|
103
104
|
});
|
|
104
105
|
return await submitDirectMusdVaultDeposit({
|
|
106
|
+
fromBlock,
|
|
105
107
|
request,
|
|
106
108
|
sourceAmountRaw,
|
|
107
109
|
transaction,
|
|
@@ -116,12 +118,16 @@ exports.submitDirectMusdAfterFiatCompletion = submitDirectMusdAfterFiatCompletio
|
|
|
116
118
|
* Submits the direct mUSD Money Account vault batch after fiat settlement.
|
|
117
119
|
*
|
|
118
120
|
* @param options - Submit options.
|
|
121
|
+
* @param options.fromBlock - Optional Monad block baseline for CHOMP
|
|
122
|
+
* idempotency scanning; sourced from the ramps settlement tx receipt via
|
|
123
|
+
* {@link resolveSourceAmountRaw}. When omitted the CHOMP checks are skipped.
|
|
119
124
|
* @param options.request - Strategy execute request.
|
|
120
125
|
* @param options.sourceAmountRaw - Settled source amount in raw mUSD units.
|
|
121
126
|
* @param options.transaction - Original Money Account transaction.
|
|
122
|
-
* @returns Hash of the final submitted child transaction
|
|
127
|
+
* @returns Hash of the final submitted child transaction (or the CHOMP deposit
|
|
128
|
+
* hash), if available.
|
|
123
129
|
*/
|
|
124
|
-
async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, transaction, }) {
|
|
130
|
+
async function submitDirectMusdVaultDeposit({ fromBlock, request, sourceAmountRaw, transaction, }) {
|
|
125
131
|
const { messenger } = request;
|
|
126
132
|
const transactionId = transaction.id;
|
|
127
133
|
const moneyAccountAddress = transaction.txParams.from;
|
|
@@ -167,6 +173,18 @@ async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, transact
|
|
|
167
173
|
tx.requiredAssets[0].amount = `0x${BigInt(sourceAmountRaw).toString(16)}`;
|
|
168
174
|
}
|
|
169
175
|
});
|
|
176
|
+
// CHOMP pre-check: skip addTransactionBatch entirely if CHOMP has already
|
|
177
|
+
// auto-vaulted the funds during or before the checkout window.
|
|
178
|
+
const preChompHash = await tryFindChompDeposit({
|
|
179
|
+
fromBlock,
|
|
180
|
+
messenger,
|
|
181
|
+
moneyAccountAddress,
|
|
182
|
+
sourceAmountRaw,
|
|
183
|
+
transactionId,
|
|
184
|
+
});
|
|
185
|
+
if (preChompHash) {
|
|
186
|
+
return { transactionHash: preChompHash };
|
|
187
|
+
}
|
|
170
188
|
const networkClientId = (0, provider_1.getNetworkClientId)(messenger, constants_2.MUSD_MONAD_FIAT_ASSET.chainId);
|
|
171
189
|
const transactionIds = [];
|
|
172
190
|
const { end } = (0, transaction_1.collectTransactionIds)(constants_2.MUSD_MONAD_FIAT_ASSET.chainId, moneyAccountAddress, messenger, (id) => {
|
|
@@ -212,6 +230,18 @@ async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, transact
|
|
|
212
230
|
});
|
|
213
231
|
}
|
|
214
232
|
catch (error) {
|
|
233
|
+
// CHOMP post-check: CHOMP may have won the race between pre-check and
|
|
234
|
+
// submit. Return the CHOMP hash instead of surfacing a Vault-prefixed error.
|
|
235
|
+
const postChompHash = await tryFindChompDeposit({
|
|
236
|
+
fromBlock,
|
|
237
|
+
messenger,
|
|
238
|
+
moneyAccountAddress,
|
|
239
|
+
sourceAmountRaw,
|
|
240
|
+
transactionId,
|
|
241
|
+
});
|
|
242
|
+
if (postChompHash) {
|
|
243
|
+
return { transactionHash: postChompHash };
|
|
244
|
+
}
|
|
215
245
|
throw (0, error_prefix_1.prefixError)(error, VAULT_ERROR_PREFIX);
|
|
216
246
|
}
|
|
217
247
|
finally {
|
|
@@ -300,4 +330,21 @@ function combineDirectMusdFiatQuote({ amountFiat, fiatQuote, messenger, moneyAcc
|
|
|
300
330
|
function getRampsProviderFee(fiatQuote) {
|
|
301
331
|
return new bignumber_js_1.BigNumber(fiatQuote.quote.providerFee ?? 0).plus(fiatQuote.quote.networkFee ?? 0);
|
|
302
332
|
}
|
|
333
|
+
async function tryFindChompDeposit({ fromBlock, messenger, moneyAccountAddress, sourceAmountRaw, transactionId, }) {
|
|
334
|
+
if (!fromBlock) {
|
|
335
|
+
return undefined;
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
return await (0, chomp_1.findRecentChompVaultDeposit)({
|
|
339
|
+
fromBlock,
|
|
340
|
+
messenger,
|
|
341
|
+
moneyAccountAddress,
|
|
342
|
+
sourceAmountRaw,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
catch (chompError) {
|
|
346
|
+
log('CHOMP check failed', { chompError, transactionId });
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
303
350
|
//# sourceMappingURL=fiat-direct-musd.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fiat-direct-musd.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"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","sourcesContent":["import { ORIGIN_METAMASK } from '@metamask/controller-utils';\nimport type {\n Quote as RampsQuote,\n RampsOrder,\n} from '@metamask/ramps-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n PayStrategyGetQuotesRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { prefixError } from '../../utils/error-prefix';\nimport { getFiatVaultDisabled } from '../../utils/feature-flags';\nimport { getNetworkClientId } from '../../utils/provider';\nimport { buildCaipAssetType, getTokenInfo } from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { MUSD_MONAD_FIAT_ASSET } from './constants';\nimport type { FiatQuote } from './types';\nimport {\n getRampsQuote,\n getRawSourceAmountFromOrderCryptoAmount,\n resolveSourceAmountRaw,\n validateOrderAsset,\n} from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-direct-musd');\nconst DIRECT_MUSD_ERROR_PREFIX = 'Direct mUSD: ';\nconst VAULT_ERROR_PREFIX = 'Vault: ';\n\n/**\n * Returns a direct mUSD fiat quote to the Money Account.\n *\n * @param options - Direct quote options.\n * @param options.amountFiat - Fiat amount entered by the user.\n * @param options.fiatPaymentMethod - Selected fiat payment method.\n * @param options.messenger - Controller messenger.\n * @param options.moneyAccountAddress - Money Account receiving the on-ramped mUSD.\n * @param options.requiredToken - Required token from the original Money Account transaction.\n * @param options.transactionId - Transaction ID for state updates and logs.\n * @returns Direct mUSD Fiat quote, or undefined when unavailable.\n */\nexport async function getDirectMusdFiatQuote({\n amountFiat,\n fiatPaymentMethod,\n messenger,\n moneyAccountAddress,\n requiredToken,\n transactionId,\n}: {\n amountFiat: string;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n transactionId: string;\n}): Promise<TransactionPayQuote<FiatQuote> | undefined> {\n try {\n const adjustedAmount = Number(amountFiat);\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount for direct mUSD quote');\n }\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n errorMessage: 'No matching ramps quote found for direct mUSD provider',\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n fiatPaymentMethod,\n messenger,\n walletAddress: moneyAccountAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment: TransactionFiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n fiatPayment.caipAssetId = buildCaipAssetType(\n MUSD_MONAD_FIAT_ASSET.chainId,\n MUSD_MONAD_FIAT_ASSET.address,\n );\n },\n transactionId,\n });\n\n log('Direct mUSD fiat quote flow', {\n amountFiat,\n moneyAccountAddress,\n transactionId,\n });\n\n return combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n });\n } catch (error) {\n log('Direct mUSD fiat quote failed', { error, transactionId });\n return undefined;\n }\n}\n\n/**\n * Detects a direct mUSD Money Account quote from its stored request marker.\n *\n * @param quote - Quote to inspect.\n * @returns True when the quote originated from the direct mUSD fiat path.\n */\nexport function isDirectMusdMoneyAccountQuote(\n quote: Pick<TransactionPayQuote<unknown>, 'request'> | undefined,\n): boolean {\n return quote?.request.isDirectMusdMoneyAccount === true;\n}\n\n/**\n * Submits the direct mUSD post-Ramp path after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.order - Completed fiat order.\n * @param options.request - Strategy execute request.\n * @returns Hash of the submitted direct mUSD transaction, if available.\n */\nexport async function submitDirectMusdAfterFiatCompletion({\n order,\n request,\n}: {\n order: RampsOrder;\n request: PayStrategyExecuteRequest<FiatQuote>;\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger, transaction } = request;\n\n try {\n validateOrderAsset({\n expectedAsset: MUSD_MONAD_FIAT_ASSET,\n orderCrypto: order.cryptoCurrency,\n transactionId: transaction.id,\n });\n\n const sourceAmountRaw = await resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n walletAddress: transaction.txParams.from as Hex,\n });\n\n return await submitDirectMusdVaultDeposit({\n request,\n sourceAmountRaw,\n transaction,\n });\n } catch (error) {\n throw prefixError(error, DIRECT_MUSD_ERROR_PREFIX);\n }\n}\n\n/**\n * Submits the direct mUSD Money Account vault batch after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.request - Strategy execute request.\n * @param options.sourceAmountRaw - Settled source amount in raw mUSD units.\n * @param options.transaction - Original Money Account transaction.\n * @returns Hash of the final submitted child transaction, if available.\n */\nexport async function submitDirectMusdVaultDeposit({\n request,\n sourceAmountRaw,\n transaction,\n}: {\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n const moneyAccountAddress = transaction.txParams.from as Hex | undefined;\n\n if (!moneyAccountAddress) {\n throw new Error('Missing Money Account address');\n }\n\n if (getFiatVaultDisabled(messenger)) {\n log('Skipping direct mUSD vault deposit because vaultDisabled is enabled', {\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n });\n\n return { transactionHash: '0x' };\n }\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n {\n amount: sourceAmountRaw,\n transaction: updatedTransaction,\n },\n );\n\n if (!updates.length) {\n throw new Error('No amount updates');\n }\n\n const nestedTransactions = updatedTransaction.nestedTransactions?.map(\n (nestedTransaction) => ({ ...nestedTransaction }),\n );\n\n if (!nestedTransactions?.length) {\n throw new Error('Missing nested transactions');\n }\n\n for (const { nestedTransactionIndex, data } of updates) {\n if (nestedTransactions[nestedTransactionIndex]) {\n nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Direct mUSD fiat: update vault amount',\n },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${BigInt(sourceAmountRaw).toString(\n 16,\n )}`;\n }\n },\n );\n\n const networkClientId = getNetworkClientId(\n messenger,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n const transactionIds: string[] = [];\n const { end } = collectTransactionIds(\n MUSD_MONAD_FIAT_ASSET.chainId,\n moneyAccountAddress,\n messenger,\n (id) => {\n transactionIds.push(id);\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Add required transaction ID from direct mUSD vault submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(id);\n },\n );\n },\n );\n\n log('Submitting direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n });\n\n try {\n await messenger.call('TransactionController:addTransactionBatch', {\n disableHook: true,\n disableSequential: true,\n disableUpgrade: true,\n from: moneyAccountAddress,\n isGasFeeSponsored: true,\n isInternal: true,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n skipInitialGasEstimate: true,\n transactions: nestedTransactions.map((nestedTransaction, index) => ({\n params: {\n data: nestedTransaction.data,\n to: nestedTransaction.to,\n value: nestedTransaction.value ?? '0x0',\n },\n type:\n index === 0\n ? (nestedTransaction.type ?? TransactionType.tokenMethodApprove)\n : TransactionType.contractInteraction,\n })),\n });\n } catch (error) {\n throw prefixError(error, VAULT_ERROR_PREFIX);\n } finally {\n end();\n }\n\n log('Submitted direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n if (!transactionIds.length) {\n throw new Error('No transactions submitted');\n }\n\n await Promise.all(\n transactionIds.map((id) => waitForTransactionConfirmed(id, messenger)),\n );\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n if (!hash) {\n throw new Error('Missing transaction hash');\n }\n\n log('Confirmed direct mUSD vault deposit', {\n hash,\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n return { transactionHash: hash as Hex };\n}\n\nfunction combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n}: {\n amountFiat: string;\n fiatQuote: RampsQuote;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n}): TransactionPayQuote<FiatQuote> {\n const tokenInfo = getTokenInfo(\n messenger,\n MUSD_MONAD_FIAT_ASSET.address,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error('Unable to resolve mUSD token info for direct fiat quote');\n }\n\n const sourceAmountRaw = getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount: fiatQuote.quote.amountOut,\n decimals: tokenInfo.decimals,\n });\n const rampsProviderFee = getRampsProviderFee(fiatQuote).toString(10);\n const sourceAmountHuman = new BigNumber(sourceAmountRaw)\n .shiftedBy(-tokenInfo.decimals)\n .toString(10);\n\n return {\n dust: { fiat: '0', usd: '0' },\n estimatedDuration: 0,\n fees: {\n metaMask: { fiat: '0', usd: '0' },\n provider: { fiat: rampsProviderFee, usd: rampsProviderFee },\n providerFiat: { fiat: rampsProviderFee, usd: rampsProviderFee },\n sourceNetwork: {\n estimate: { fiat: '0', human: '0', raw: '0', usd: '0' },\n max: { fiat: '0', human: '0', raw: '0', usd: '0' },\n },\n targetNetwork: { fiat: '0', usd: '0' },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: undefined,\n },\n request: {\n from: moneyAccountAddress,\n isDirectMusdMoneyAccount: true,\n recipient: moneyAccountAddress,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: MUSD_MONAD_FIAT_ASSET.chainId,\n sourceTokenAddress: MUSD_MONAD_FIAT_ASSET.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: sourceAmountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n },\n sourceAmount: {\n fiat: amountFiat,\n human: sourceAmountHuman,\n raw: sourceAmountRaw,\n usd: amountFiat,\n },\n strategy: TransactionPayStrategy.Fiat,\n targetAmount: { fiat: amountFiat, usd: amountFiat },\n };\n}\n\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fiat-direct-musd.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"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","sourcesContent":["import { ORIGIN_METAMASK } from '@metamask/controller-utils';\nimport type {\n Quote as RampsQuote,\n RampsOrder,\n} from '@metamask/ramps-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n PayStrategyGetQuotesRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { prefixError } from '../../utils/error-prefix';\nimport { getFiatVaultDisabled } from '../../utils/feature-flags';\nimport { getNetworkClientId } from '../../utils/provider';\nimport { buildCaipAssetType, getTokenInfo } from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { findRecentChompVaultDeposit } from './chomp';\nimport { MUSD_MONAD_FIAT_ASSET } from './constants';\nimport type { FiatQuote } from './types';\nimport {\n getRampsQuote,\n getRawSourceAmountFromOrderCryptoAmount,\n resolveSourceAmountRaw,\n validateOrderAsset,\n} from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-direct-musd');\nconst DIRECT_MUSD_ERROR_PREFIX = 'Direct mUSD: ';\nconst VAULT_ERROR_PREFIX = 'Vault: ';\n\n/**\n * Returns a direct mUSD fiat quote to the Money Account.\n *\n * @param options - Direct quote options.\n * @param options.amountFiat - Fiat amount entered by the user.\n * @param options.fiatPaymentMethod - Selected fiat payment method.\n * @param options.messenger - Controller messenger.\n * @param options.moneyAccountAddress - Money Account receiving the on-ramped mUSD.\n * @param options.requiredToken - Required token from the original Money Account transaction.\n * @param options.transactionId - Transaction ID for state updates and logs.\n * @returns Direct mUSD Fiat quote, or undefined when unavailable.\n */\nexport async function getDirectMusdFiatQuote({\n amountFiat,\n fiatPaymentMethod,\n messenger,\n moneyAccountAddress,\n requiredToken,\n transactionId,\n}: {\n amountFiat: string;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n transactionId: string;\n}): Promise<TransactionPayQuote<FiatQuote> | undefined> {\n try {\n const adjustedAmount = Number(amountFiat);\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount for direct mUSD quote');\n }\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n errorMessage: 'No matching ramps quote found for direct mUSD provider',\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n fiatPaymentMethod,\n messenger,\n walletAddress: moneyAccountAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment: TransactionFiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n fiatPayment.caipAssetId = buildCaipAssetType(\n MUSD_MONAD_FIAT_ASSET.chainId,\n MUSD_MONAD_FIAT_ASSET.address,\n );\n },\n transactionId,\n });\n\n log('Direct mUSD fiat quote flow', {\n amountFiat,\n moneyAccountAddress,\n transactionId,\n });\n\n return combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n });\n } catch (error) {\n log('Direct mUSD fiat quote failed', { error, transactionId });\n return undefined;\n }\n}\n\n/**\n * Detects a direct mUSD Money Account quote from its stored request marker.\n *\n * @param quote - Quote to inspect.\n * @returns True when the quote originated from the direct mUSD fiat path.\n */\nexport function isDirectMusdMoneyAccountQuote(\n quote: Pick<TransactionPayQuote<unknown>, 'request'> | undefined,\n): boolean {\n return quote?.request.isDirectMusdMoneyAccount === true;\n}\n\n/**\n * Submits the direct mUSD post-Ramp path after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.order - Completed fiat order.\n * @param options.request - Strategy execute request.\n * @returns Hash of the submitted direct mUSD transaction, if available.\n */\nexport async function submitDirectMusdAfterFiatCompletion({\n order,\n request,\n}: {\n order: RampsOrder;\n request: PayStrategyExecuteRequest<FiatQuote>;\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger, transaction } = request;\n\n try {\n validateOrderAsset({\n expectedAsset: MUSD_MONAD_FIAT_ASSET,\n orderCrypto: order.cryptoCurrency,\n transactionId: transaction.id,\n });\n\n const { amountRaw: sourceAmountRaw, fromBlock } =\n await resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n walletAddress: transaction.txParams.from as Hex,\n });\n\n return await submitDirectMusdVaultDeposit({\n fromBlock,\n request,\n sourceAmountRaw,\n transaction,\n });\n } catch (error) {\n throw prefixError(error, DIRECT_MUSD_ERROR_PREFIX);\n }\n}\n\n/**\n * Submits the direct mUSD Money Account vault batch after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.fromBlock - Optional Monad block baseline for CHOMP\n * idempotency scanning; sourced from the ramps settlement tx receipt via\n * {@link resolveSourceAmountRaw}. When omitted the CHOMP checks are skipped.\n * @param options.request - Strategy execute request.\n * @param options.sourceAmountRaw - Settled source amount in raw mUSD units.\n * @param options.transaction - Original Money Account transaction.\n * @returns Hash of the final submitted child transaction (or the CHOMP deposit\n * hash), if available.\n */\nexport async function submitDirectMusdVaultDeposit({\n fromBlock,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n fromBlock?: Hex;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n const moneyAccountAddress = transaction.txParams.from as Hex | undefined;\n\n if (!moneyAccountAddress) {\n throw new Error('Missing Money Account address');\n }\n\n if (getFiatVaultDisabled(messenger)) {\n log('Skipping direct mUSD vault deposit because vaultDisabled is enabled', {\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n });\n\n return { transactionHash: '0x' };\n }\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n {\n amount: sourceAmountRaw,\n transaction: updatedTransaction,\n },\n );\n\n if (!updates.length) {\n throw new Error('No amount updates');\n }\n\n const nestedTransactions = updatedTransaction.nestedTransactions?.map(\n (nestedTransaction) => ({ ...nestedTransaction }),\n );\n\n if (!nestedTransactions?.length) {\n throw new Error('Missing nested transactions');\n }\n\n for (const { nestedTransactionIndex, data } of updates) {\n if (nestedTransactions[nestedTransactionIndex]) {\n nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Direct mUSD fiat: update vault amount',\n },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${BigInt(sourceAmountRaw).toString(\n 16,\n )}`;\n }\n },\n );\n\n // CHOMP pre-check: skip addTransactionBatch entirely if CHOMP has already\n // auto-vaulted the funds during or before the checkout window.\n const preChompHash = await tryFindChompDeposit({\n fromBlock,\n messenger,\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n });\n\n if (preChompHash) {\n return { transactionHash: preChompHash };\n }\n\n const networkClientId = getNetworkClientId(\n messenger,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n const transactionIds: string[] = [];\n const { end } = collectTransactionIds(\n MUSD_MONAD_FIAT_ASSET.chainId,\n moneyAccountAddress,\n messenger,\n (id) => {\n transactionIds.push(id);\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Add required transaction ID from direct mUSD vault submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(id);\n },\n );\n },\n );\n\n log('Submitting direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n });\n\n try {\n await messenger.call('TransactionController:addTransactionBatch', {\n disableHook: true,\n disableSequential: true,\n disableUpgrade: true,\n from: moneyAccountAddress,\n isGasFeeSponsored: true,\n isInternal: true,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n skipInitialGasEstimate: true,\n transactions: nestedTransactions.map((nestedTransaction, index) => ({\n params: {\n data: nestedTransaction.data,\n to: nestedTransaction.to,\n value: nestedTransaction.value ?? '0x0',\n },\n type:\n index === 0\n ? (nestedTransaction.type ?? TransactionType.tokenMethodApprove)\n : TransactionType.contractInteraction,\n })),\n });\n } catch (error) {\n // CHOMP post-check: CHOMP may have won the race between pre-check and\n // submit. Return the CHOMP hash instead of surfacing a Vault-prefixed error.\n const postChompHash = await tryFindChompDeposit({\n fromBlock,\n messenger,\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n });\n\n if (postChompHash) {\n return { transactionHash: postChompHash };\n }\n\n throw prefixError(error, VAULT_ERROR_PREFIX);\n } finally {\n end();\n }\n\n log('Submitted direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n if (!transactionIds.length) {\n throw new Error('No transactions submitted');\n }\n\n await Promise.all(\n transactionIds.map((id) => waitForTransactionConfirmed(id, messenger)),\n );\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n if (!hash) {\n throw new Error('Missing transaction hash');\n }\n\n log('Confirmed direct mUSD vault deposit', {\n hash,\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n return { transactionHash: hash as Hex };\n}\n\nfunction combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n}: {\n amountFiat: string;\n fiatQuote: RampsQuote;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n}): TransactionPayQuote<FiatQuote> {\n const tokenInfo = getTokenInfo(\n messenger,\n MUSD_MONAD_FIAT_ASSET.address,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error('Unable to resolve mUSD token info for direct fiat quote');\n }\n\n const sourceAmountRaw = getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount: fiatQuote.quote.amountOut,\n decimals: tokenInfo.decimals,\n });\n const rampsProviderFee = getRampsProviderFee(fiatQuote).toString(10);\n const sourceAmountHuman = new BigNumber(sourceAmountRaw)\n .shiftedBy(-tokenInfo.decimals)\n .toString(10);\n\n return {\n dust: { fiat: '0', usd: '0' },\n estimatedDuration: 0,\n fees: {\n metaMask: { fiat: '0', usd: '0' },\n provider: { fiat: rampsProviderFee, usd: rampsProviderFee },\n providerFiat: { fiat: rampsProviderFee, usd: rampsProviderFee },\n sourceNetwork: {\n estimate: { fiat: '0', human: '0', raw: '0', usd: '0' },\n max: { fiat: '0', human: '0', raw: '0', usd: '0' },\n },\n targetNetwork: { fiat: '0', usd: '0' },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: undefined,\n },\n request: {\n from: moneyAccountAddress,\n isDirectMusdMoneyAccount: true,\n recipient: moneyAccountAddress,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: MUSD_MONAD_FIAT_ASSET.chainId,\n sourceTokenAddress: MUSD_MONAD_FIAT_ASSET.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: sourceAmountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n },\n sourceAmount: {\n fiat: amountFiat,\n human: sourceAmountHuman,\n raw: sourceAmountRaw,\n usd: amountFiat,\n },\n strategy: TransactionPayStrategy.Fiat,\n targetAmount: { fiat: amountFiat, usd: amountFiat },\n };\n}\n\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nasync function tryFindChompDeposit({\n fromBlock,\n messenger,\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n}: {\n fromBlock: Hex | undefined;\n messenger: PayStrategyExecuteRequest<FiatQuote>['messenger'];\n moneyAccountAddress: Hex;\n sourceAmountRaw: string;\n transactionId: string;\n}): Promise<Hex | undefined> {\n if (!fromBlock) {\n return undefined;\n }\n\n try {\n return await findRecentChompVaultDeposit({\n fromBlock,\n messenger,\n moneyAccountAddress,\n sourceAmountRaw,\n });\n } catch (chompError) {\n log('CHOMP check failed', { chompError, transactionId });\n return undefined;\n }\n}\n"]}
|
|
@@ -47,12 +47,17 @@ export declare function submitDirectMusdAfterFiatCompletion({ order, request, }:
|
|
|
47
47
|
* Submits the direct mUSD Money Account vault batch after fiat settlement.
|
|
48
48
|
*
|
|
49
49
|
* @param options - Submit options.
|
|
50
|
+
* @param options.fromBlock - Optional Monad block baseline for CHOMP
|
|
51
|
+
* idempotency scanning; sourced from the ramps settlement tx receipt via
|
|
52
|
+
* {@link resolveSourceAmountRaw}. When omitted the CHOMP checks are skipped.
|
|
50
53
|
* @param options.request - Strategy execute request.
|
|
51
54
|
* @param options.sourceAmountRaw - Settled source amount in raw mUSD units.
|
|
52
55
|
* @param options.transaction - Original Money Account transaction.
|
|
53
|
-
* @returns Hash of the final submitted child transaction
|
|
56
|
+
* @returns Hash of the final submitted child transaction (or the CHOMP deposit
|
|
57
|
+
* hash), if available.
|
|
54
58
|
*/
|
|
55
|
-
export declare function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, transaction, }: {
|
|
59
|
+
export declare function submitDirectMusdVaultDeposit({ fromBlock, request, sourceAmountRaw, transaction, }: {
|
|
60
|
+
fromBlock?: Hex;
|
|
56
61
|
request: PayStrategyExecuteRequest<FiatQuote>;
|
|
57
62
|
sourceAmountRaw: string;
|
|
58
63
|
transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fiat-direct-musd.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,UAAU,EACX,mCAAmC;AAEpC,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAE3B,2BAA2B,EAC3B,mBAAmB,EACpB,wBAAoB;
|
|
1
|
+
{"version":3,"file":"fiat-direct-musd.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,UAAU,EACX,mCAAmC;AAEpC,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAE3B,2BAA2B,EAC3B,mBAAmB,EACpB,wBAAoB;AAarB,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAYzC;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,aAAa,GACd,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC;IACpD,mBAAmB,EAAE,GAAG,CAAC;IACzB,aAAa,EAAE,2BAA2B,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,CA6CtD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,GAAG,SAAS,GAC/D,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAsB,mCAAmC,CAAC,EACxD,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;CAC/C,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CA2BrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,SAAS,EACT,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAiMrC"}
|
|
@@ -47,12 +47,17 @@ export declare function submitDirectMusdAfterFiatCompletion({ order, request, }:
|
|
|
47
47
|
* Submits the direct mUSD Money Account vault batch after fiat settlement.
|
|
48
48
|
*
|
|
49
49
|
* @param options - Submit options.
|
|
50
|
+
* @param options.fromBlock - Optional Monad block baseline for CHOMP
|
|
51
|
+
* idempotency scanning; sourced from the ramps settlement tx receipt via
|
|
52
|
+
* {@link resolveSourceAmountRaw}. When omitted the CHOMP checks are skipped.
|
|
50
53
|
* @param options.request - Strategy execute request.
|
|
51
54
|
* @param options.sourceAmountRaw - Settled source amount in raw mUSD units.
|
|
52
55
|
* @param options.transaction - Original Money Account transaction.
|
|
53
|
-
* @returns Hash of the final submitted child transaction
|
|
56
|
+
* @returns Hash of the final submitted child transaction (or the CHOMP deposit
|
|
57
|
+
* hash), if available.
|
|
54
58
|
*/
|
|
55
|
-
export declare function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, transaction, }: {
|
|
59
|
+
export declare function submitDirectMusdVaultDeposit({ fromBlock, request, sourceAmountRaw, transaction, }: {
|
|
60
|
+
fromBlock?: Hex;
|
|
56
61
|
request: PayStrategyExecuteRequest<FiatQuote>;
|
|
57
62
|
sourceAmountRaw: string;
|
|
58
63
|
transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fiat-direct-musd.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,UAAU,EACX,mCAAmC;AAEpC,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAE3B,2BAA2B,EAC3B,mBAAmB,EACpB,wBAAoB;
|
|
1
|
+
{"version":3,"file":"fiat-direct-musd.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,UAAU,EACX,mCAAmC;AAEpC,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,yBAAyB,EACzB,2BAA2B,EAE3B,2BAA2B,EAC3B,mBAAmB,EACpB,wBAAoB;AAarB,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAYzC;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,aAAa,GACd,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,2BAA2B,CAAC,WAAW,CAAC,CAAC;IACpD,mBAAmB,EAAE,GAAG,CAAC;IACzB,aAAa,EAAE,2BAA2B,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,CA6CtD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,GAAG,SAAS,GAC/D,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAsB,mCAAmC,CAAC,EACxD,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;CAC/C,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CA2BrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,SAAS,EACT,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAiMrC"}
|
|
@@ -9,6 +9,7 @@ import { getFiatVaultDisabled } from "../../utils/feature-flags.mjs";
|
|
|
9
9
|
import { getNetworkClientId } from "../../utils/provider.mjs";
|
|
10
10
|
import { buildCaipAssetType, getTokenInfo } from "../../utils/token.mjs";
|
|
11
11
|
import { collectTransactionIds, getTransaction, updateTransaction, waitForTransactionConfirmed } from "../../utils/transaction.mjs";
|
|
12
|
+
import { findRecentChompVaultDeposit } from "./chomp.mjs";
|
|
12
13
|
import { MUSD_MONAD_FIAT_ASSET } from "./constants.mjs";
|
|
13
14
|
import { getRampsQuote, getRawSourceAmountFromOrderCryptoAmount, resolveSourceAmountRaw, validateOrderAsset } from "./utils.mjs";
|
|
14
15
|
const log = createModuleLogger(projectLogger, 'fiat-direct-musd');
|
|
@@ -90,13 +91,14 @@ export async function submitDirectMusdAfterFiatCompletion({ order, request, }) {
|
|
|
90
91
|
orderCrypto: order.cryptoCurrency,
|
|
91
92
|
transactionId: transaction.id,
|
|
92
93
|
});
|
|
93
|
-
const sourceAmountRaw = await resolveSourceAmountRaw({
|
|
94
|
+
const { amountRaw: sourceAmountRaw, fromBlock } = await resolveSourceAmountRaw({
|
|
94
95
|
messenger,
|
|
95
96
|
order,
|
|
96
97
|
fiatAsset: MUSD_MONAD_FIAT_ASSET,
|
|
97
98
|
walletAddress: transaction.txParams.from,
|
|
98
99
|
});
|
|
99
100
|
return await submitDirectMusdVaultDeposit({
|
|
101
|
+
fromBlock,
|
|
100
102
|
request,
|
|
101
103
|
sourceAmountRaw,
|
|
102
104
|
transaction,
|
|
@@ -110,12 +112,16 @@ export async function submitDirectMusdAfterFiatCompletion({ order, request, }) {
|
|
|
110
112
|
* Submits the direct mUSD Money Account vault batch after fiat settlement.
|
|
111
113
|
*
|
|
112
114
|
* @param options - Submit options.
|
|
115
|
+
* @param options.fromBlock - Optional Monad block baseline for CHOMP
|
|
116
|
+
* idempotency scanning; sourced from the ramps settlement tx receipt via
|
|
117
|
+
* {@link resolveSourceAmountRaw}. When omitted the CHOMP checks are skipped.
|
|
113
118
|
* @param options.request - Strategy execute request.
|
|
114
119
|
* @param options.sourceAmountRaw - Settled source amount in raw mUSD units.
|
|
115
120
|
* @param options.transaction - Original Money Account transaction.
|
|
116
|
-
* @returns Hash of the final submitted child transaction
|
|
121
|
+
* @returns Hash of the final submitted child transaction (or the CHOMP deposit
|
|
122
|
+
* hash), if available.
|
|
117
123
|
*/
|
|
118
|
-
export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, transaction, }) {
|
|
124
|
+
export async function submitDirectMusdVaultDeposit({ fromBlock, request, sourceAmountRaw, transaction, }) {
|
|
119
125
|
const { messenger } = request;
|
|
120
126
|
const transactionId = transaction.id;
|
|
121
127
|
const moneyAccountAddress = transaction.txParams.from;
|
|
@@ -161,6 +167,18 @@ export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, t
|
|
|
161
167
|
tx.requiredAssets[0].amount = `0x${BigInt(sourceAmountRaw).toString(16)}`;
|
|
162
168
|
}
|
|
163
169
|
});
|
|
170
|
+
// CHOMP pre-check: skip addTransactionBatch entirely if CHOMP has already
|
|
171
|
+
// auto-vaulted the funds during or before the checkout window.
|
|
172
|
+
const preChompHash = await tryFindChompDeposit({
|
|
173
|
+
fromBlock,
|
|
174
|
+
messenger,
|
|
175
|
+
moneyAccountAddress,
|
|
176
|
+
sourceAmountRaw,
|
|
177
|
+
transactionId,
|
|
178
|
+
});
|
|
179
|
+
if (preChompHash) {
|
|
180
|
+
return { transactionHash: preChompHash };
|
|
181
|
+
}
|
|
164
182
|
const networkClientId = getNetworkClientId(messenger, MUSD_MONAD_FIAT_ASSET.chainId);
|
|
165
183
|
const transactionIds = [];
|
|
166
184
|
const { end } = collectTransactionIds(MUSD_MONAD_FIAT_ASSET.chainId, moneyAccountAddress, messenger, (id) => {
|
|
@@ -206,6 +224,18 @@ export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, t
|
|
|
206
224
|
});
|
|
207
225
|
}
|
|
208
226
|
catch (error) {
|
|
227
|
+
// CHOMP post-check: CHOMP may have won the race between pre-check and
|
|
228
|
+
// submit. Return the CHOMP hash instead of surfacing a Vault-prefixed error.
|
|
229
|
+
const postChompHash = await tryFindChompDeposit({
|
|
230
|
+
fromBlock,
|
|
231
|
+
messenger,
|
|
232
|
+
moneyAccountAddress,
|
|
233
|
+
sourceAmountRaw,
|
|
234
|
+
transactionId,
|
|
235
|
+
});
|
|
236
|
+
if (postChompHash) {
|
|
237
|
+
return { transactionHash: postChompHash };
|
|
238
|
+
}
|
|
209
239
|
throw prefixError(error, VAULT_ERROR_PREFIX);
|
|
210
240
|
}
|
|
211
241
|
finally {
|
|
@@ -293,4 +323,21 @@ function combineDirectMusdFiatQuote({ amountFiat, fiatQuote, messenger, moneyAcc
|
|
|
293
323
|
function getRampsProviderFee(fiatQuote) {
|
|
294
324
|
return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(fiatQuote.quote.networkFee ?? 0);
|
|
295
325
|
}
|
|
326
|
+
async function tryFindChompDeposit({ fromBlock, messenger, moneyAccountAddress, sourceAmountRaw, transactionId, }) {
|
|
327
|
+
if (!fromBlock) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
return await findRecentChompVaultDeposit({
|
|
332
|
+
fromBlock,
|
|
333
|
+
messenger,
|
|
334
|
+
moneyAccountAddress,
|
|
335
|
+
sourceAmountRaw,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
catch (chompError) {
|
|
339
|
+
log('CHOMP check failed', { chompError, transactionId });
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
296
343
|
//# sourceMappingURL=fiat-direct-musd.mjs.map
|