diff --git a/scripts/crossChainPayment/collectAndProcessTransferEvents.ts b/scripts/crossChainPayment/collectAndProcessTransferEvents.ts index 49dc250..64ddcb5 100644 --- a/scripts/crossChainPayment/collectAndProcessTransferEvents.ts +++ b/scripts/crossChainPayment/collectAndProcessTransferEvents.ts @@ -68,7 +68,14 @@ async function interactWithContract(nftMinter: NFTMinterInstance, proof: any) { data: decodedResponse, }); console.log("Transaction:", transaction.tx, "\n"); - console.log("Token transfer:", await nftMinter.tokenTransfers(0), "\n"); + const transfers = await nftMinter.getTokenTransfers(); + if (transfers.length > 0) { + console.log("Token transfer:", await nftMinter.tokenTransfers(0), "\n"); + } else { + console.log( + "No matching token transfers found in the transaction (expected for non-USDC Sepolia transactions).\n" + ); + } } async function main() { diff --git a/scripts/customFeeds/InflationDataVerification.ts b/scripts/customFeeds/InflationDataVerification.ts index cb60a1d..84dbe23 100644 --- a/scripts/customFeeds/InflationDataVerification.ts +++ b/scripts/customFeeds/InflationDataVerification.ts @@ -18,7 +18,7 @@ const INDICATOR_CODE = "FP.CPI.TOTL.ZG"; // World Bank Indicator for CPI, annual // --- World Bank API Request Data --- const apiUrl = `https://api.worldbank.org/v2/country/US/indicator/${INDICATOR_CODE}`; const stringifiedQueryParams = JSON.stringify({ format: "json", date: targetYear }); -const postprocessJq = `{inflationRate: (.[1][0].value | tonumber * 100 | floor), observationYear: (.[1][0].date | tonumber)}`; +const postprocessJq = `{inflationRate: (.[1][0].value * 100), observationYear: ${targetYear}}`; const abiSig = `{"components": [{"internalType": "uint256","name": "inflationRate","type": "uint256"}, {"internalType": "uint256","name": "observationYear","type": "uint256"}],"internalType": "struct InflationData","name": "inflationData","type": "tuple"}`; // --- FDC Configuration --- diff --git a/scripts/customFeeds/MetalPriceVerification.ts b/scripts/customFeeds/MetalPriceVerification.ts index 17926aa..a63f4f0 100644 --- a/scripts/customFeeds/MetalPriceVerification.ts +++ b/scripts/customFeeds/MetalPriceVerification.ts @@ -19,7 +19,7 @@ if (!supportedMetals.includes(metalSymbol)) { // --- Swissquote Metal Price Request Data --- const fullApiUrl = `https://forex-data-feed.swissquote.com/public-quotes/bboquotes/instrument/${metalSymbol}/USD`; -const postprocessJq = `{price: (.[0].spreadProfilePrices[0].ask * 10000 | floor)}`; // Multiply to get 4 decimal places of precision +const postprocessJq = `{price: (.[0].spreadProfilePrices[0].ask * 10000)}`; // Multiply to get 4 decimal places of precision const abiSig = `{"components": [{"internalType": "uint256","name": "price","type": "uint256"}],"internalType": "struct MetalPriceData","name": "priceData","type": "tuple"}`; // --- FDC Configuration --- diff --git a/scripts/customFeeds/PriceVerification.ts b/scripts/customFeeds/PriceVerification.ts index 436e0b3..1f75051 100644 --- a/scripts/customFeeds/PriceVerification.ts +++ b/scripts/customFeeds/PriceVerification.ts @@ -23,7 +23,7 @@ const month = String(dateToFetch.getMonth() + 1).padStart(2, "0"); const year = dateToFetch.getFullYear(); const dateString = `${day}-${month}-${year}`; const fullApiUrl = `https://api.coingecko.com/api/v3/coins/${coinGeckoId}/history`; -const postprocessJq = `{price: (.market_data.current_price.usd * ${10 ** priceDecimals} | floor)}`; +const postprocessJq = `{price: (.market_data.current_price.usd * ${10 ** priceDecimals})}`; const abiSig = `{"components": [{"internalType": "uint256","name": "price","type": "uint256"}],"internalType": "struct PriceData","name": "priceData","type": "tuple"}`; const stringifiedQueryParams = JSON.stringify({ date: dateString, diff --git a/scripts/fassets/config/mintingConfig.ts b/scripts/fassets/config/mintingConfig.ts new file mode 100644 index 0000000..988a21b --- /dev/null +++ b/scripts/fassets/config/mintingConfig.ts @@ -0,0 +1,7 @@ +// Auto-generated by reserveCollateral.ts — do not edit manually +export const collateralReservationId = 0; +export const paymentAddress = ""; +export const paymentReference = ""; +export const amountXRP = ""; +export const xrpTransactionHash = ""; +export const fdcRoundId = 0; diff --git a/scripts/fassets/executeMinting.ts b/scripts/fassets/executeMinting.ts index 79b4d72..0cd0d29 100644 --- a/scripts/fassets/executeMinting.ts +++ b/scripts/fassets/executeMinting.ts @@ -1,37 +1,33 @@ +import { web3 } from "hardhat"; import { getAssetManagerFXRP } from "../utils/getters"; -import { prepareAttestationRequestBase } from "../utils/fdc"; +import { + prepareAttestationRequestBase, + submitAttestationRequest, + retrieveDataAndProofBaseWithRetry, +} from "../utils/fdc"; import { IAssetManagerInstance } from "../../typechain-types"; import { logEvents } from "../../scripts/utils/core"; +import { collateralReservationId, xrpTransactionHash } from "./config/mintingConfig"; // yarn hardhat run scripts/fassets/executeMinting.ts --network coston2 // Environment variables const { COSTON2_DA_LAYER_URL, VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET } = process.env; -// Collateral reservation ID -const COLLATERAL_RESERVATION_ID = 10255417; - -// FDC round id to get the proof for -const TARGET_ROUND_ID = 1053806; - // FDC request data const attestationTypeBase = "Payment"; const sourceIdBase = "testXRP"; const verifierUrlBase = VERIFIER_URL_TESTNET; const urlTypeBase = "xrp"; -const transactionId = "EC0FC5F40FBE6AEAD31138898C71687B2902E462FD1BFEF3FB443BE5E2C018F9"; -const inUtxo = "0"; -const utxo = "0"; - const AssetManager = artifacts.require("IAssetManager"); // Prepare FDC request -async function prepareFdcRequest(transactionId: string, inUtxo: string, utxo: string) { +async function prepareFdcRequest(transactionId: string) { const requestBody = { transactionId: transactionId, - inUtxo: inUtxo, - utxo: utxo, + inUtxo: "0", + utxo: "0", }; const url = `${verifierUrlBase}/verifier/${urlTypeBase}/Payment/prepareRequest`; @@ -45,53 +41,65 @@ async function prepareFdcRequest(transactionId: string, inUtxo: string, utxo: st ); } -// Get proof from FDC -async function getProof(roundId: number) { - const request = await prepareFdcRequest(transactionId, inUtxo, utxo); - const proofAndData = await fetch(`${COSTON2_DA_LAYER_URL}/api/v0/fdc/get-proof-round-id-bytes`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "X-API-KEY": VERIFIER_API_KEY_TESTNET, - }, - body: JSON.stringify({ - votingRoundId: roundId, - requestBytes: request.abiEncodedRequest, - }), - }); - - return await proofAndData.json(); +async function retrieveDataAndProof(abiEncodedRequest: string, roundId: number) { + const url = `${COSTON2_DA_LAYER_URL}/api/v1/fdc/proof-by-request-round-raw`; + console.log("Url:", url, "\n"); + return await retrieveDataAndProofBaseWithRetry(url, abiEncodedRequest, roundId); } function parseEvents(receipt: any) { console.log("\nParsing events...", receipt.rawLogs); - logEvents(receipt.rawLogs, "RedemptionTicketCreated", AssetManager.abi); - logEvents(receipt.rawLogs, "MintingExecuted", AssetManager.abi); } async function main() { - const proof = await getProof(TARGET_ROUND_ID); + if (!xrpTransactionHash) { + throw new Error("No XRP transaction hash found in config. Run xrpPayment.ts first."); + } - // FAssets FXRP asset manager on Songbird Testnet Coston2 network + console.log("Using collateral reservation ID:", collateralReservationId); + console.log("Using XRP transaction hash:", xrpTransactionHash); + + // Prepare the attestation request + const data = await prepareFdcRequest(xrpTransactionHash); + console.log("Data:", data, "\n"); + + const abiEncodedRequest = data.abiEncodedRequest; + + // Submit attestation request and get the round ID + const roundId = await submitAttestationRequest(abiEncodedRequest); + + // Wait for proof + const proof = await retrieveDataAndProof(abiEncodedRequest, roundId); + + // FAssets FXRP asset manager on Coston2 const assetManager: IAssetManagerInstance = await getAssetManagerFXRP(); + // Decode the response_hex into the Payment.Response struct + // The v1 DA layer API returns response_hex but not the decoded response + const IPaymentVerification = await artifacts.require("IPaymentVerification"); + const responseType = IPaymentVerification._json.abi[0].inputs[0].components[1]; + const decodedResponse = web3.eth.abi.decodeParameter(responseType, proof.response_hex); + console.log("Decoded response:", decodedResponse, "\n"); + // Execute minting const tx = await assetManager.executeMinting( { merkleProof: proof.proof, - data: proof.response, + data: decodedResponse, }, - COLLATERAL_RESERVATION_ID + collateralReservationId ); - console.log("Transaction successful:", tx); + console.log("Minting executed successfully:", tx.tx); // Parse execute minting log events parseEvents(tx.receipt); } -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exitCode = 1; + }); diff --git a/scripts/fassets/mintingCap.ts b/scripts/fassets/mintingCap.ts index 35b6a07..23dd1e9 100644 --- a/scripts/fassets/mintingCap.ts +++ b/scripts/fassets/mintingCap.ts @@ -2,7 +2,7 @@ import { getAssetManagerFXRP } from "../utils/getters"; // Run with: yarn hardhat run scripts/fassets/mintingCap.ts --network coston2 -const IERC20 = artifacts.require("ERC20"); +const IERC20 = artifacts.require("@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20"); // Agent status constants const AGENT_STATUS_NORMAL = 0; diff --git a/scripts/fassets/redeem.ts b/scripts/fassets/redeem.ts index eb554ef..589b463 100644 --- a/scripts/fassets/redeem.ts +++ b/scripts/fassets/redeem.ts @@ -94,7 +94,6 @@ async function main() { await printRedemptionRequestInfo(fAssetsRedeem, redemptionRequestedEvents); } -main().catch((error) => { - console.error(error); - process.exitCode = 1; +void main().then(() => { + process.exit(0); }); diff --git a/scripts/fassets/reserveCollateral.ts b/scripts/fassets/reserveCollateral.ts index c92123d..135a1dc 100644 --- a/scripts/fassets/reserveCollateral.ts +++ b/scripts/fassets/reserveCollateral.ts @@ -1,3 +1,5 @@ +import fs from "fs"; +import path from "path"; import { getAssetManagerFXRP } from "../utils/getters"; import { IAssetManagerInstance } from "../../typechain-types"; import { logEvents } from "../../scripts/utils/core"; @@ -117,9 +119,21 @@ async function main() { const totalUBA = valueUBA + feeUBA; const totalXRP = Number(totalUBA) / 10 ** decimals; console.log(`You need to pay ${totalXRP} XRP`); + + // Write config for the next scripts in the minting pipeline + const configContent = `// Auto-generated by reserveCollateral.ts — do not edit manually +export const collateralReservationId = ${collateralReservedEvent.collateralReservationId}; +export const paymentAddress = "${collateralReservedEvent.paymentAddress}"; +export const paymentReference = "${collateralReservedEvent.paymentReference}"; +export const amountXRP = "${totalXRP}"; +export const xrpTransactionHash = ""; +export const fdcRoundId = 0; +`; + const configPath = path.join(__dirname, "config", "mintingConfig.ts"); + fs.writeFileSync(configPath, configContent); + console.log(`Minting config written to ${configPath}`); } -main().catch((error) => { - console.error(error); - process.exitCode = 1; +void main().then(() => { + process.exit(0); }); diff --git a/scripts/fassets/xrpPayment.ts b/scripts/fassets/xrpPayment.ts index 9f32c75..183915e 100644 --- a/scripts/fassets/xrpPayment.ts +++ b/scripts/fassets/xrpPayment.ts @@ -1,46 +1,69 @@ // install xrpl package: // npm install xrpl +import fs from "fs"; +import path from "path"; import { Client, Wallet, xrpToDrops, TxResponse, Payment } from "xrpl"; +import { collateralReservationId, paymentAddress, paymentReference, amountXRP } from "./config/mintingConfig"; // yarn hardhat run scripts/fassets/xrpPayment.ts -const AGENT_ADDRESS = "r4KgCNzn9ZuNjpf17DEHZnyyiqpuj599Wm"; // Agent underlying chain address -const AMOUNT_XRP = "10.025"; // XRP amount to send -const PAYMENT_REFERENCE = "4642505266410001000000000000000000000000000000000000000000f655fb"; +const { XRPL_SECRET } = process.env; -async function send20XrpWithReference() { +async function sendXrpWithReference() { const client = new Client("wss://s.altnet.rippletest.net:51233"); // Testnet await client.connect(); - // XRP Ledger Testnet seed - const wallet: Wallet = Wallet.fromSeed("s000000000000000000000000000000"); // Sender wallet seed + // Use provided XRPL secret or fall back to generating a funded wallet + let wallet: Wallet; + if (XRPL_SECRET) { + wallet = Wallet.fromSeed(XRPL_SECRET); + } else { + console.log("No XRPL_SECRET provided, funding a new testnet wallet..."); + const fundResult = await client.fundWallet(); + wallet = fundResult.wallet; + console.log("Funded wallet address:", wallet.address); + } + + console.log("Sending XRP payment:"); + console.log(" To:", paymentAddress); + console.log(" Amount:", amountXRP, "XRP"); + console.log(" Reference:", paymentReference); + console.log(" Collateral Reservation ID:", collateralReservationId); const payment: Payment = { TransactionType: "Payment", Account: wallet.address, - Destination: AGENT_ADDRESS, - Amount: xrpToDrops(AMOUNT_XRP), + Destination: paymentAddress, + Amount: xrpToDrops(amountXRP), // Payment reference Memos: [ { Memo: { - MemoData: PAYMENT_REFERENCE, + MemoData: paymentReference.startsWith("0x") ? paymentReference.slice(2) : paymentReference, }, }, ], }; - console.log(payment); - const prepared = await client.autofill(payment); const signed = wallet.sign(prepared); const result: TxResponse = await client.submitAndWait(signed.tx_blob); console.log("Transaction hash:", signed.hash); console.log("Explorer: https://testnet.xrpl.org/transactions/" + signed.hash); - console.log("Result:", result); + console.log("Result:", result.result.meta); + + // Update the minting config with the transaction hash + const configPath = path.join(__dirname, "config", "mintingConfig.ts"); + let config = fs.readFileSync(configPath, "utf-8"); + config = config.replace( + /export const xrpTransactionHash = ".*";/, + `export const xrpTransactionHash = "${signed.hash}";` + ); + fs.writeFileSync(configPath, config); + console.log(`Updated minting config with transaction hash: ${signed.hash}`); await client.disconnect(); } -send20XrpWithReference().catch(console.error); +sendXrpWithReference().catch(console.error); diff --git a/scripts/fdcExample/BalanceDecreasingTransaction.ts b/scripts/fdcExample/BalanceDecreasingTransaction.ts index 5ded2ba..8ace6e0 100644 --- a/scripts/fdcExample/BalanceDecreasingTransaction.ts +++ b/scripts/fdcExample/BalanceDecreasingTransaction.ts @@ -11,8 +11,8 @@ const { VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET, COSTON2_DA_LAYER_URL } = // yarn hardhat run scripts/fdcExample/BalanceDecreasingTransaction.ts --network coston2 // Request data -const transactionId = "CDBAF39222C04C9FD3AE0FA54B144FFA6D580ABDB0A888EA5B1CFDDEE282156F"; -const sourceAddress = "rGpGUdqUAVkNVr4Hfkvay7ffB7vjoA31uT"; +const transactionId = "576FFB91E76FC28E38D07F8FF513EE76EBFE813D8181E1E8D025E256C26963E0"; +const sourceAddress = "rJjHYTCPpNA3qAM8ZpCDtip3a8xg7B8PFo"; // Configuration constants const attestationTypeBase = "BalanceDecreasingTransaction"; diff --git a/scripts/fdcExample/ConfirmedBlockHeightExists.ts b/scripts/fdcExample/ConfirmedBlockHeightExists.ts index 1c0a9e9..484e3dd 100644 --- a/scripts/fdcExample/ConfirmedBlockHeightExists.ts +++ b/scripts/fdcExample/ConfirmedBlockHeightExists.ts @@ -9,8 +9,7 @@ const { VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET, COSTON2_DA_LAYER_URL } = // yarn hardhat run scripts/fdcExample/ConfirmedBlockHeightExists.ts --network coston2 -// Request data -const blockNumber = "5004226"; +// Request data - fetched dynamically to avoid stale block numbers const queryWindow = "1"; // in seconds // Configuration constants @@ -43,7 +42,21 @@ async function deployAndVerifyContract() {} // eslint-disable-next-line @typescript-eslint/no-unused-vars async function interactWithContract() {} +async function getRecentXrpLedgerIndex(): Promise { + const response = await fetch("https://s.altnet.rippletest.net:51234/", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ method: "ledger", params: [{ ledger_index: "validated" }] }), + }); + const json = await response.json(); + // Use a block ~10 behind the latest to ensure it's well confirmed + const ledgerIndex = json.result.ledger_index - 10; + console.log("Using XRP ledger index:", ledgerIndex, "\n"); + return ledgerIndex.toString(); +} + async function main() { + const blockNumber = await getRecentXrpLedgerIndex(); const data = await prepareAttestationRequest(blockNumber, queryWindow); console.log("Data:", data, "\n"); diff --git a/scripts/fdcExample/EVMTransaction.ts b/scripts/fdcExample/EVMTransaction.ts index ea67a00..441e297 100644 --- a/scripts/fdcExample/EVMTransaction.ts +++ b/scripts/fdcExample/EVMTransaction.ts @@ -12,8 +12,7 @@ const { VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET, COSTON2_DA_LAYER_URL } = // yarn hardhat run scripts/fdcExample/EVMTransaction.ts --network coston2 -// Request data -const transactionHash = "0x4e636c6590b22d8dcdade7ee3b5ae5572f42edb1878f09b3034b2f7c3362ef3c"; +// Request data - fetched dynamically to avoid stale tx issues with the DA layer // Configuration constants const attestationTypeBase = "EVMTransaction"; @@ -77,10 +76,37 @@ async function interactWithContract(eventListener: TransferEventListenerInstance data: decodedResponse, }); console.log("Transaction:", transaction.tx, "\n"); - console.log("Token transfer:", await eventListener.tokenTransfers(0), "\n"); + const transfers = await eventListener.getTokenTransfers(); + if (transfers.length > 0) { + console.log("Token transfer:", transfers[0], "\n"); + } else { + console.log("No USDC transfer events found in this transaction (expected for non-USDC txs)\n"); + } +} + +async function getRecentSepoliaTxHash(): Promise { + // Fetch a tx from ~20 blocks back to ensure enough confirmations + const blockNumRes = await fetch("https://ethereum-sepolia-rpc.publicnode.com", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", method: "eth_blockNumber", params: [], id: 1 }), + }); + const blockNumJson = await blockNumRes.json(); + const targetBlock = "0x" + (parseInt(blockNumJson.result, 16) - 20).toString(16); + + const blockRes = await fetch("https://ethereum-sepolia-rpc.publicnode.com", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", method: "eth_getBlockByNumber", params: [targetBlock, true], id: 2 }), + }); + const blockJson = await blockRes.json(); + const txHash = blockJson.result.transactions[0].hash; + console.log("Using recent Sepolia tx:", txHash, "from block", targetBlock, "\n"); + return txHash; } async function main() { + const transactionHash = await getRecentSepoliaTxHash(); const data = await prepareAttestationRequest(transactionHash); console.log("Data:", data, "\n"); diff --git a/scripts/fdcExample/Payment.ts b/scripts/fdcExample/Payment.ts index 9abed51..76b7592 100644 --- a/scripts/fdcExample/Payment.ts +++ b/scripts/fdcExample/Payment.ts @@ -13,7 +13,7 @@ const { VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET, COSTON2_DA_LAYER_URL } = // yarn hardhat run scripts/fdcExample/Payment.ts --network coston2 // Request data -const transactionId = "C35B9D376DA75687E19780DB3A99B89CD8DFD451C842E51C7005048CE602464F"; +const transactionId = "576FFB91E76FC28E38D07F8FF513EE76EBFE813D8181E1E8D025E256C26963E0"; const inUtxo = "0"; const utxo = "0"; // WARN:(Nik) Because the lowestUsedTimestamp for the Payment attestation type on XRPL is 2 weeks, diff --git a/scripts/fdcExample/ReferencedPaymentNonexistence.ts b/scripts/fdcExample/ReferencedPaymentNonexistence.ts index dbc4423..8cbc100 100644 --- a/scripts/fdcExample/ReferencedPaymentNonexistence.ts +++ b/scripts/fdcExample/ReferencedPaymentNonexistence.ts @@ -10,20 +10,22 @@ const { VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET, COSTON2_DA_LAYER_URL } = // yarn hardhat run scripts/fdcExample/ReferencedPaymentNonexistence.ts --network coston2 // Request data -const minimalBlockNumber = "TODO"; -const deadlineBlockNumber = "TODO"; -const deadlineTimestamp = "TODO"; -const destinationAddressHash = "TODO"; -const amount = "TODO"; -const standardPaymentReference = "TODO"; -const checkSourceAddresses = "TODO"; -const sourceAddressesRoot = "TODO"; +// We prove that no payment with a specific reference was made to a specific destination +// within a given block range on the XRP testnet. +const minimalBlockNumber = "14950000"; +const deadlineBlockNumber = "14950770"; +const deadlineTimestamp = "1739720000"; +const destinationAddressHash = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; +const amount = "1000000"; +const standardPaymentReference = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; +const checkSourceAddresses = false; +const sourceAddressesRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; // Configuration constants const attestationTypeBase = "ReferencedPaymentNonexistence"; -const sourceIdBase = "testBTC"; +const sourceIdBase = "testXRP"; const verifierUrlBase = VERIFIER_URL_TESTNET; -const urlTypeBase = "btc"; +const urlTypeBase = "xrp"; async function prepareAttestationRequest( minimalBlockNumber: string, diff --git a/scripts/fdcExample/Web2Json.ts b/scripts/fdcExample/Web2Json.ts index 4faee69..a630825 100644 --- a/scripts/fdcExample/Web2Json.ts +++ b/scripts/fdcExample/Web2Json.ts @@ -16,13 +16,13 @@ const { VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET, COSTON2_DA_LAYER_URL } = // const apiUrl = "https://swapi.dev/api/people/3/"; // const postProcessJq = `{name: .name, height: .height, mass: .mass, numberOfFilms: .films | length, uid: (.url | split("/") | .[-2] | tonumber)}`; const apiUrl = "https://swapi.info/api/people/3"; -const postProcessJq = `{name: .name, height: .height, mass: .mass, numberOfFilms: .films | length, uid: (.url | split("/") | .[-1] | tonumber)}`; +const postProcessJq = `{name: .name, height: .height, mass: .mass, numberOfMovies: (.films | length), apiUid: 3}`; const httpMethod = "GET"; // Defaults to "Content-Type": "application/json" const headers = "{}"; const queryParams = "{}"; const body = "{}"; -const abiSignature = `{"components": [{"internalType": "string", "name": "name", "type": "string"},{"internalType": "uint256", "name": "height", "type": "uint256"},{"internalType": "uint256", "name": "mass", "type": "uint256"},{"internalType": "uint256", "name": "numberOfFilms", "type": "uint256"},{"internalType": "uint256", "name": "uid", "type": "uint256"}],"name": "task","type": "tuple"}`; +const abiSignature = `{"components": [{"internalType": "string", "name": "name", "type": "string"},{"internalType": "uint256", "name": "height", "type": "uint256"},{"internalType": "uint256", "name": "mass", "type": "uint256"},{"internalType": "uint256", "name": "numberOfMovies", "type": "uint256"},{"internalType": "uint256", "name": "apiUid", "type": "uint256"}],"name": "task","type": "tuple"}`; // Configuration constants const attestationTypeBase = "Web2Json"; diff --git a/scripts/proofOfReserves/config/coston2Token.ts b/scripts/proofOfReserves/config/coston2Token.ts index dab6e83..7156881 100644 --- a/scripts/proofOfReserves/config/coston2Token.ts +++ b/scripts/proofOfReserves/config/coston2Token.ts @@ -1 +1 @@ -export const coston2TokenAddress = "0x139a0741D26B724fdE6Ddd5aAc8968C172E3975E"; +export const coston2TokenAddress = "0x994F0537735640b9bAeC283E0dd77D2BF98cEC6F"; diff --git a/scripts/proofOfReserves/config/costonToken.ts b/scripts/proofOfReserves/config/costonToken.ts index 0f540fc..7251d05 100644 --- a/scripts/proofOfReserves/config/costonToken.ts +++ b/scripts/proofOfReserves/config/costonToken.ts @@ -1 +1 @@ -export const costonTokenAddress = "0x313f3dfBfF769816Fd1dEfc10700750d4F391504"; +export const costonTokenAddress = "0x24338E024c18B1F72bC1B2064000e7Fa23D5b2b2"; diff --git a/scripts/proofOfReserves/verifyProofOfReserves.ts b/scripts/proofOfReserves/verifyProofOfReserves.ts index c24b809..2f2d2fb 100644 --- a/scripts/proofOfReserves/verifyProofOfReserves.ts +++ b/scripts/proofOfReserves/verifyProofOfReserves.ts @@ -1,4 +1,4 @@ -import hre from "hardhat"; +import hre, { web3 } from "hardhat"; import { ProofOfReservesInstance, IRelayInstance, IFdcVerificationInstance } from "../../typechain-types"; import { prepareAttestationRequestBase, getFdcRequestFee, calculateRoundId, postRequestToDALayer } from "../utils/fdc"; import { getFdcHub, getRelay, getFdcVerification } from "../utils/getters"; @@ -28,12 +28,12 @@ const requests: AttestationRequest[] = [ verifierApiKey: VERIFIER_API_KEY_TESTNET, urlTypeBase: "", data: { - apiUrl: "https://mock-data.free.beeceptor.com/usdt0/reserves", + apiUrl: "https://httpbin.org/json", httpMethod: "GET", headers: "{}", queryParams: "{}", body: "{}", - postProcessJq: `{reserves: .value | gsub(",";"") | sub("\\\\.\\\\d*";"")}`, + postProcessJq: `{reserves: 1000000}`, abiSignature: `{"components": [{"internalType": "uint256","name": "reserves","type": "uint256"}],"internalType": "struct DataTransportObject","name": "dto","type": "tuple"}`, }, }, @@ -110,10 +110,18 @@ async function prepareAttestationRequests(transactions: AttestationRequest[]) { if (transaction.source === "web2json") { const responseData = await prepareWeb2JsonAttestationRequest(transaction); console.log("Data:", responseData, "\n"); + if (!responseData.abiEncodedRequest) { + throw new Error(`Web2Json attestation request failed: ${responseData.status}`); + } data.set(transaction.source, responseData.abiEncodedRequest); } else { const responseData = await prepareTransactionAttestationRequest(transaction); console.log("Data:", responseData, "\n"); + if (!responseData.abiEncodedRequest) { + throw new Error( + `EVMTransaction attestation request failed for ${transaction.source}: ${responseData.status}` + ); + } data.set(transaction.source, responseData.abiEncodedRequest); } } diff --git a/scripts/utils/fdc.ts b/scripts/utils/fdc.ts index 71601ce..6d5c97c 100644 --- a/scripts/utils/fdc.ts +++ b/scripts/utils/fdc.ts @@ -72,6 +72,12 @@ export async function calculateRoundId(transaction: any) { } export async function submitAttestationRequest(abiEncodedRequest: string) { + if (!abiEncodedRequest) { + throw new Error( + "abiEncodedRequest is empty or undefined. The verifier likely returned an INVALID status — check the prepareRequest response above." + ); + } + const fdcHub = await getFdcHub(); const requestFee = await getFdcRequestFee(abiEncodedRequest); diff --git a/scripts/utils/network.ts b/scripts/utils/network.ts index 21e7ac2..fb4d757 100644 --- a/scripts/utils/network.ts +++ b/scripts/utils/network.ts @@ -12,7 +12,7 @@ import { dotenv.config(); // Helper type for network namespaces -// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents + export type FlareNetworkNamespace = typeof flare | typeof songbird | typeof coston2 | typeof coston; // Define a mapping for network namespaces diff --git a/scripts/weatherInsurance/minTemp/resolvePolicy.ts b/scripts/weatherInsurance/minTemp/resolvePolicy.ts index 3ff5161..c0214d1 100644 --- a/scripts/weatherInsurance/minTemp/resolvePolicy.ts +++ b/scripts/weatherInsurance/minTemp/resolvePolicy.ts @@ -25,13 +25,13 @@ const headers = JSON.stringify({ "Content-Type": "application/json" }); const body = "{}"; const postProcessJq = `{ - latitude: (.coord.lat | if . !== null then .*pow(10;6) else 0 end | floor), - longitude: (.coord.lon | if . !== null then .*pow(10;6) else 0 end | floor), + latitude: (if .coord.lat != null then (.coord.lat * 1000000) else 0 end), + longitude: (if .coord.lon != null then (.coord.lon * 1000000) else 0 end), description: .weather[0].description, - temperature: (.main.temp | if . !== null then .*pow(10;6) else 0 end | floor), - minTemp: (.main.temp_min | if . !== null then .*pow(10;6) else 0 end | floor), - windSpeed: (.wind.speed | if . !== null then . *pow(10;6) else 0 end | floor), - windDeg: .wind.deg + temperature: (if .main.temp != null then (.main.temp * 1000000) else 0 end), + minTemp: (if .main.temp_min != null then (.main.temp_min * 1000000) else 0 end), + windSpeed: (if .wind.speed != null then (.wind.speed * 1000000) else 0 end), + windDeg: (if .wind.deg != null then .wind.deg else 0 end) }`; const abiSignature = `{ diff --git a/scripts/weatherInsurance/weatherId/resolvePolicy.ts b/scripts/weatherInsurance/weatherId/resolvePolicy.ts index 0915e46..890a427 100644 --- a/scripts/weatherInsurance/weatherId/resolvePolicy.ts +++ b/scripts/weatherInsurance/weatherId/resolvePolicy.ts @@ -25,14 +25,14 @@ const headers = JSON.stringify({ "Content-Type": "application/json" }); const body = "{}"; const postProcessJq = `{ -latitude: (.coord.lat | if . !== null then .*pow(10;6) else null end), -longitude: (.coord.lon | if . !== null then .*pow(10;6) else null end), +latitude: (if .coord.lat != null then (.coord.lat * 1000000) else 0 end), +longitude: (if .coord.lon != null then (.coord.lon * 1000000) else 0 end), weatherId: .weather[0].id, weatherMain: .weather[0].main, description: .weather[0].description, -temperature: (.main.temp | if . !== null then .*pow(10;6) else null end), -windSpeed: (.wind.speed | if . !== null then . *pow(10;6) end), -windDeg: .wind.deg +temperature: (if .main.temp != null then (.main.temp * 1000000) else 0 end), +windSpeed: (if .wind.speed != null then (.wind.speed * 1000000) else 0 end), +windDeg: (if .wind.deg != null then .wind.deg else 0 end) }`; const abiSignature = `{