Update payment flow
This commit is contained in:
parent
4c291dc307
commit
f5d82d5292
@ -1,14 +1,12 @@
|
||||
# Client-side environment variables (must be prefixed with NEXT_PUBLIC_)
|
||||
|
||||
# Solana Token Payment Configuration
|
||||
NEXT_PUBLIC_SOLANA_RPC_URL=https://skilled-prettiest-seed.solana-mainnet.quiknode.pro/eeecfebd04e345f69f1900cc3483cbbfea02a158
|
||||
NEXT_PUBLIC_SOLANA_WEBSOCKET_URL=wss://skilled-prettiest-seed.solana-mainnet.quiknode.pro/
|
||||
NEXT_PUBLIC_SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
|
||||
NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS=71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg
|
||||
NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS=
|
||||
NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL=GOR
|
||||
NEXT_PUBLIC_SOLANA_TOKEN_NAME=GOR Token
|
||||
NEXT_PUBLIC_SOLANA_TOKEN_DECIMALS=6
|
||||
NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT=50
|
||||
NEXT_PUBLIC_MIN_SOLANA_PAYMENT_AMOUNT=50
|
||||
|
||||
# UI Configuration (optional)
|
||||
NEXT_PUBLIC_DOMAIN_SUFFIX=
|
||||
@ -30,7 +28,4 @@ REGISTRY_GAS_PRICE=0.001
|
||||
# Application Configuration
|
||||
APP_NAME=gor-deploy
|
||||
DEPLOYER_LRN=
|
||||
|
||||
# LNT Transfer Configuration (required for Solana flow)
|
||||
# Note: REGISTRY_USER_KEY is used as the prefilled account for LNT transfers
|
||||
LACONIC_TRANSFER_AMOUNT=1000000alnt
|
||||
|
||||
@ -32,13 +32,12 @@ Required environment variables:
|
||||
|
||||
Client-side (must be prefixed with NEXT_PUBLIC_):
|
||||
- `NEXT_PUBLIC_SOLANA_RPC_URL` - The RPC URL for the Solana blockchain
|
||||
- `NEXT_PUBLIC_SOLANA_WEBSOCKET_URL` - The WebSocket URL for Solana (optional)
|
||||
- `NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS` - The mint address of the SPL token to accept
|
||||
- `NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS` - The Solana address that will receive token payments
|
||||
- `NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL` - The token symbol to display (e.g., "GOR")
|
||||
- `NEXT_PUBLIC_SOLANA_TOKEN_NAME` - The full token name (e.g., "GOR Token")
|
||||
- `NEXT_PUBLIC_SOLANA_TOKEN_DECIMALS` - The number of decimals for the token (e.g., 6)
|
||||
- `NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT` - The fixed payment amount required (e.g., 50)
|
||||
- `NEXT_PUBLIC_MIN_SOLANA_PAYMENT_AMOUNT` - The fixed payment amount required (e.g., 50)
|
||||
- `NEXT_PUBLIC_DOMAIN_SUFFIX` - Optional suffix to append to DNS names in the UI (e.g. ".example.com")
|
||||
- `NEXT_PUBLIC_EXAMPLE_URL` - Example URL to pre-fill in the URL form (e.g. "https://github.com/cerc-io/laconic-registry-cli")
|
||||
|
||||
@ -51,7 +50,6 @@ Server-side:
|
||||
- `REGISTRY_USER_KEY` - The private key for Laconic Registry transactions (also used for LNT transfers)
|
||||
- `APP_NAME` - The name of the application (used in record creation, defaults to "gor-deploy")
|
||||
- `DEPLOYER_LRN` - The LRN of the deployer
|
||||
- `LACONIC_SERVICE_PROVIDER_ADDRESS` - The Laconic address to receive LNT transfers
|
||||
- `LACONIC_TRANSFER_AMOUNT` - The amount of LNT to transfer (e.g., "1000000alnt")
|
||||
|
||||
## Installation
|
||||
@ -189,10 +187,10 @@ docker run -p 3000:3000 --env-file .env.production gor-deploy
|
||||
|
||||
- **Wrong token**: Verify the `NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS` matches your desired SPL token.
|
||||
- **Incorrect decimals**: Ensure `NEXT_PUBLIC_SOLANA_TOKEN_DECIMALS` matches the token's actual decimal count.
|
||||
- **Payment amount**: Adjust `NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT` to the desired payment amount.
|
||||
- **Payment amount**: Adjust `NEXT_PUBLIC_MIN_SOLANA_PAYMENT_AMOUNT` to the desired payment amount.
|
||||
|
||||
### Laconic Registry Issues
|
||||
|
||||
- **Failed to create record**: Check that your REGISTRY_USER_KEY and REGISTRY_BOND_ID are correctly set.
|
||||
- **LNT transfer errors**: Ensure your REGISTRY_USER_KEY has sufficient LNT balance and the LACONIC_SERVICE_PROVIDER_ADDRESS is valid.
|
||||
- **LNT transfer errors**: Ensure your REGISTRY_USER_KEY has sufficient LNT balance.
|
||||
- **Transaction verification errors**: Ensure your SOLANA_RPC_URL is accessible and returns correct transaction data.
|
||||
|
||||
427
package-lock.json
generated
427
package-lock.json
generated
@ -1,16 +1,15 @@
|
||||
{
|
||||
"name": "atom-deploy",
|
||||
"name": "gor-deploy",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "atom-deploy",
|
||||
"name": "gor-deploy",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@cerc-io/registry-sdk": "^0.2.11",
|
||||
"@cosmjs/stargate": "^0.32.3",
|
||||
"@keplr-wallet/types": "^0.12.71",
|
||||
"@solana/spl-token": "^0.4.13",
|
||||
"@solana/web3.js": "^1.98.2",
|
||||
"axios": "^1.6.8",
|
||||
@ -1754,17 +1753,6 @@
|
||||
"multiformats": "^9.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@keplr-wallet/types": {
|
||||
"version": "0.12.230",
|
||||
"resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.12.230.tgz",
|
||||
"integrity": "sha512-fyd/Wt2accJ/avOHOWc8kOtJCLKrHtyVjMNvmxmIZw5uFYPLKFxeVUSLy1AB4JmhDupcZvshocFO1hOe+WkUMQ==",
|
||||
"dependencies": {
|
||||
"long": "^4.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"starknet": "^6"
|
||||
}
|
||||
},
|
||||
"node_modules/@metamask/eth-sig-util": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz",
|
||||
@ -2080,40 +2068,6 @@
|
||||
"integrity": "sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@scure/base": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz",
|
||||
"integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@scure/starknet": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@scure/starknet/-/starknet-1.1.0.tgz",
|
||||
"integrity": "sha512-83g3M6Ix2qRsPN4wqLDqiRZ2GBNbjVWfboJE/9UjfG+MHr6oDSu/CWgy8hsBSJejr09DkkL+l0Ze4KVrlCIdtQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@noble/curves": "~1.7.0",
|
||||
"@noble/hashes": "~1.6.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@scure/starknet/node_modules/@noble/hashes": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz",
|
||||
"integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^14.21.3 || >=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@solana/buffer-layout": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz",
|
||||
@ -3304,21 +3258,6 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/abi-wan-kanabi": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-2.2.4.tgz",
|
||||
"integrity": "sha512-0aA81FScmJCPX+8UvkXLki3X1+yPQuWxEkqXBVKltgPAK79J+NB+Lp5DouMXa7L6f+zcRlIA/6XO7BN/q9fnvg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansicolors": "^0.3.2",
|
||||
"cardinal": "^2.1.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"generate": "dist/generate.js"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
@ -3373,19 +3312,11 @@
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
@ -3396,12 +3327,6 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansicolors": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
|
||||
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
@ -3945,19 +3870,6 @@
|
||||
"resolved": "https://registry.npmjs.org/canonical-json/-/canonical-json-0.0.4.tgz",
|
||||
"integrity": "sha512-2sW7x0m/P7dqEnO0O87U7RTVQAaa7MELcd+Jd9FA6CYgYtwJ1TlDWIYMD8nuMkH1KoThsJogqgLyklrt9d/Azw=="
|
||||
},
|
||||
"node_modules/cardinal": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
|
||||
"integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansicolors": "~0.3.2",
|
||||
"redeyed": "~2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"cdl": "bin/cdl.js"
|
||||
}
|
||||
},
|
||||
"node_modules/cborg": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/cborg/-/cborg-1.10.2.tgz",
|
||||
@ -3999,20 +3911,6 @@
|
||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
@ -4039,6 +3937,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
@ -4049,7 +3948,8 @@
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/color-string": {
|
||||
"version": "1.9.1",
|
||||
@ -4531,15 +4431,6 @@
|
||||
"es6-promise": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
@ -5174,16 +5065,6 @@
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-cookie": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-3.0.1.tgz",
|
||||
"integrity": "sha512-ZGXe8Y5Z/1FWqQ9q/CrJhkUD73DyBU9VF0hBQmEO/wPHe4A9PKTjplFDLeFX8aOsYypZUcX5Ji/eByn3VCVO3Q==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"set-cookie-parser": "^2.4.8",
|
||||
"tough-cookie": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||
@ -5296,20 +5177,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -5352,15 +5219,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
@ -5503,7 +5361,8 @@
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
@ -5895,15 +5754,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-generator-function": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
|
||||
@ -6128,16 +5978,6 @@
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/isomorphic-fetch": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz",
|
||||
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.1",
|
||||
"whatwg-fetch": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/isomorphic-ws": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
|
||||
@ -6274,18 +6114,6 @@
|
||||
"json5": "lib/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsx-ast-utils": {
|
||||
"version": "3.3.5",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
||||
@ -6738,12 +6566,6 @@
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lossless-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.0.2.tgz",
|
||||
"integrity": "sha512-+z0EaLi2UcWi8MZRxA5iTb6m4Ys4E80uftGY+yG5KNFJb5EceQXOhdW/pWJZ8m97s26u7yZZAYMcKWNztSZssA==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
@ -7185,12 +7007,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@ -7364,32 +7180,15 @@
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
|
||||
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/lupomontero"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
@ -7472,15 +7271,6 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/redeyed": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
|
||||
"integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esprima": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||
@ -7523,21 +7313,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.10",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||
@ -7800,12 +7575,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/set-cookie-parser": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
@ -8069,44 +7838,6 @@
|
||||
"integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/starknet": {
|
||||
"version": "6.24.1",
|
||||
"resolved": "https://registry.npmjs.org/starknet/-/starknet-6.24.1.tgz",
|
||||
"integrity": "sha512-g7tiCt73berhcNi41otlN3T3kxZnIvZhMi8WdC21Y6GC6zoQgbI2z1t7JAZF9c4xZiomlanwVnurcpyfEdyMpg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@noble/curves": "1.7.0",
|
||||
"@noble/hashes": "1.6.0",
|
||||
"@scure/base": "1.2.1",
|
||||
"@scure/starknet": "1.1.0",
|
||||
"abi-wan-kanabi": "^2.2.3",
|
||||
"fetch-cookie": "~3.0.0",
|
||||
"isomorphic-fetch": "~3.0.0",
|
||||
"lossless-json": "^4.0.1",
|
||||
"pako": "^2.0.4",
|
||||
"starknet-types-07": "npm:@starknet-io/types-js@^0.7.10",
|
||||
"ts-mixer": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/starknet-types-07": {
|
||||
"name": "@starknet-io/types-js",
|
||||
"version": "0.7.10",
|
||||
"resolved": "https://registry.npmjs.org/@starknet-io/types-js/-/types-js-0.7.10.tgz",
|
||||
"integrity": "sha512-1VtCqX4AHWJlRRSYGSn+4X1mqolI1Tdq62IwzoU2vUuEE72S1OlEeGhpvd6XsdqXcfHmVzYfj8k1XtKBQqwo9w==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/starknet/node_modules/@noble/hashes": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz",
|
||||
"integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^14.21.3 || >=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-chain": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz",
|
||||
@ -8138,26 +7869,6 @@
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/string.prototype.includes": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
|
||||
@ -8265,18 +7976,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
@ -8467,30 +8166,6 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
|
||||
"integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.2.0",
|
||||
"url-parse": "^1.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie/node_modules/universalify": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
@ -8508,12 +8183,6 @@
|
||||
"typescript": ">=4.8.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-mixer": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
|
||||
"integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
|
||||
@ -8667,15 +8336,6 @@
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unrs-resolver": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz",
|
||||
@ -8717,16 +8377,6 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "5.0.10",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||
@ -8760,12 +8410,6 @@
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-fetch": {
|
||||
"version": "3.6.20",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
|
||||
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
@ -8892,23 +8536,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
@ -8943,42 +8570,6 @@
|
||||
"symbol-observable": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
"@solana/spl-token": "^0.4.13",
|
||||
"@solana/web3.js": "^1.98.2",
|
||||
"axios": "^1.6.8",
|
||||
"bn.js": "^5.2.2",
|
||||
"next": "15.3.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BN from 'bn.js';
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { Registry } from '@cerc-io/registry-sdk';
|
||||
import { GasPrice } from '@cosmjs/stargate';
|
||||
@ -143,7 +144,9 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
// Verify Solana payment
|
||||
console.log('Step 0: Verifying Solana token payment...');
|
||||
const solanaPaymentResult = await verifyUnusedSolanaPayment(txHash);
|
||||
const paymentAmount = parseInt(process.env.NEXT_PUBLIC_MIN_SOLANA_PAYMENT_AMOUNT || '50');
|
||||
const tokenAmount = new BN(paymentAmount);
|
||||
const solanaPaymentResult = await verifyUnusedSolanaPayment(txHash, tokenAmount);
|
||||
|
||||
if (!solanaPaymentResult.valid) {
|
||||
console.error('Solana token payment verification failed:', solanaPaymentResult.reason);
|
||||
@ -183,7 +186,6 @@ export async function POST(request: NextRequest) {
|
||||
'REGISTRY_USER_KEY', // This is the same as the prefilled account for LNT transfers
|
||||
'DEPLOYER_LRN',
|
||||
// LNT transfer variables
|
||||
'LACONIC_SERVICE_PROVIDER_ADDRESS',
|
||||
'LACONIC_TRANSFER_AMOUNT',
|
||||
// Solana/GOR specific variables
|
||||
'NEXT_PUBLIC_SOLANA_RPC_URL',
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { sendSolanaTokenPayment } from '@/services/solana';
|
||||
import { PaymentModalProps } from '@/types';
|
||||
import { getSolanaConfig } from '@/config';
|
||||
|
||||
export default function PaymentModal({
|
||||
isOpen,
|
||||
@ -15,10 +15,9 @@ export default function PaymentModal({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
// Get configuration
|
||||
const solanaConfig = getSolanaConfig();
|
||||
const amount = solanaConfig.paymentAmount;
|
||||
const recipientAddress = solanaConfig.tokenRecipientAddress;
|
||||
// Get configuration from environment variables directly
|
||||
const amount = parseInt(process.env.NEXT_PUBLIC_MIN_SOLANA_PAYMENT_AMOUNT || '50');
|
||||
const recipientAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS;
|
||||
|
||||
const handlePayment = async () => {
|
||||
setLoading(true);
|
||||
@ -33,7 +32,8 @@ export default function PaymentModal({
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await sendSolanaTokenPayment(walletInfo.publicKey, walletInfo.walletType);
|
||||
const tokenAmount = new BN(amount);
|
||||
const result = await sendSolanaTokenPayment(walletInfo.publicKey, tokenAmount, walletInfo.walletType);
|
||||
|
||||
if (result.success && result.transactionSignature) {
|
||||
onPaymentComplete(result.transactionSignature);
|
||||
|
||||
@ -43,39 +43,10 @@ export const getAppName = (): string => {
|
||||
return process.env.APP_NAME || 'gor-deploy';
|
||||
};
|
||||
|
||||
// Solana Token Configuration (configurable)
|
||||
export const getSolanaConfig = () => {
|
||||
// Direct validation without loop to avoid the strange undefined behavior
|
||||
const rpcUrl = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
|
||||
const tokenMintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS;
|
||||
const tokenRecipientAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS;
|
||||
|
||||
if (!rpcUrl) {
|
||||
throw new Error(`Missing environment variable: NEXT_PUBLIC_SOLANA_RPC_URL`);
|
||||
}
|
||||
if (!tokenMintAddress) {
|
||||
throw new Error(`Missing environment variable: NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS`);
|
||||
}
|
||||
if (!tokenRecipientAddress) {
|
||||
throw new Error(`Missing environment variable: NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS`);
|
||||
}
|
||||
|
||||
return {
|
||||
rpcUrl,
|
||||
websocketUrl: process.env.NEXT_PUBLIC_SOLANA_WEBSOCKET_URL,
|
||||
tokenMintAddress,
|
||||
tokenRecipientAddress,
|
||||
tokenSymbol: process.env.NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL || 'TOKEN',
|
||||
tokenName: process.env.NEXT_PUBLIC_SOLANA_TOKEN_NAME || 'Solana Token',
|
||||
paymentAmount: parseInt(process.env.NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT || '50'),
|
||||
tokenDecimals: parseInt(process.env.NEXT_PUBLIC_SOLANA_TOKEN_DECIMALS || '9')
|
||||
};
|
||||
};
|
||||
|
||||
export const getLaconicTransferConfig = () => {
|
||||
const requiredEnvVars = [
|
||||
'REGISTRY_USER_KEY', // Same account as the registry user
|
||||
'LACONIC_SERVICE_PROVIDER_ADDRESS',
|
||||
'LACONIC_TRANSFER_AMOUNT'
|
||||
];
|
||||
|
||||
@ -87,7 +58,6 @@ export const getLaconicTransferConfig = () => {
|
||||
|
||||
return {
|
||||
prefilledPrivateKey: process.env.REGISTRY_USER_KEY!, // Use the same key as registry operations
|
||||
serviceProviderAddress: process.env.LACONIC_SERVICE_PROVIDER_ADDRESS!,
|
||||
transferAmount: process.env.LACONIC_TRANSFER_AMOUNT!
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,58 +1,53 @@
|
||||
import assert from 'assert';
|
||||
import BN from 'bn.js';
|
||||
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
|
||||
import {
|
||||
TOKEN_PROGRAM_ID,
|
||||
createTransferInstruction,
|
||||
createAssociatedTokenAccountInstruction,
|
||||
getAssociatedTokenAddress
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID
|
||||
} from '@solana/spl-token';
|
||||
import { getSolanaConfig } from '../config';
|
||||
import { SolanaPaymentResult, SolanaWalletType, SolanaWalletState } from '../types';
|
||||
|
||||
let connection: Connection | null = null;
|
||||
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
|
||||
assert(process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS, 'SOLANA_TOKEN_MINT_ADDRESS is required');
|
||||
assert(process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS, 'SOLANA_TOKEN_RECIPIENT_ADDRESS is required');
|
||||
|
||||
const getConnection = (): Connection => {
|
||||
if (!connection) {
|
||||
const config = getSolanaConfig();
|
||||
connection = new Connection(
|
||||
config.rpcUrl,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
wsEndpoint: config.websocketUrl,
|
||||
confirmTransactionInitialTimeout: 60000,
|
||||
}
|
||||
);
|
||||
}
|
||||
return connection;
|
||||
};
|
||||
const TOKEN_MINT = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS;
|
||||
const PAYMENT_RECEIVER_ADDRESS = process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS;
|
||||
const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
|
||||
|
||||
const connection = new Connection(SOLANA_RPC_URL);
|
||||
|
||||
export const connectSolanaWallet = async (walletType: SolanaWalletType): Promise<SolanaWalletState> => {
|
||||
try {
|
||||
let wallet: any = null;
|
||||
|
||||
if (walletType === 'phantom') {
|
||||
if (!window.phantom?.solana) {
|
||||
throw new Error('Phantom wallet not found. Please install Phantom browser extension.');
|
||||
}
|
||||
wallet = window.phantom.solana;
|
||||
const response = await window.phantom.solana.connect();
|
||||
return {
|
||||
connected: true,
|
||||
publicKey: response.publicKey.toString(),
|
||||
walletType
|
||||
};
|
||||
} else if (walletType === 'solflare') {
|
||||
if (!window.solflare) {
|
||||
throw new Error('Solflare wallet not found. Please install Solflare browser extension.');
|
||||
}
|
||||
wallet = window.solflare;
|
||||
await window.solflare.connect();
|
||||
const publicKey = window.solflare.publicKey?.toString();
|
||||
if (!publicKey) {
|
||||
throw new Error('Failed to get public key from Solflare wallet');
|
||||
}
|
||||
return {
|
||||
connected: true,
|
||||
publicKey,
|
||||
walletType
|
||||
};
|
||||
}
|
||||
|
||||
if (!wallet) {
|
||||
throw new Error(`${walletType} wallet not available`);
|
||||
}
|
||||
|
||||
const response = await wallet.connect();
|
||||
const publicKey = response.publicKey.toString();
|
||||
|
||||
return {
|
||||
connected: true,
|
||||
publicKey,
|
||||
walletType
|
||||
};
|
||||
throw new Error(`Unsupported wallet type: ${walletType}`);
|
||||
} catch (error) {
|
||||
console.error('Failed to connect to Solana wallet:', error);
|
||||
throw error;
|
||||
@ -77,49 +72,60 @@ export const disconnectSolanaWallet = async (walletType: SolanaWalletType): Prom
|
||||
}
|
||||
};
|
||||
|
||||
export const sendSolanaTokenPayment = async (
|
||||
async function findAssociatedTokenAddress(
|
||||
walletAddress: PublicKey,
|
||||
tokenMintAddress: PublicKey
|
||||
): Promise<PublicKey> {
|
||||
return PublicKey.findProgramAddressSync(
|
||||
[
|
||||
walletAddress.toBuffer(),
|
||||
TOKEN_PROGRAM_ID.toBuffer(),
|
||||
tokenMintAddress.toBuffer(),
|
||||
],
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID
|
||||
)[0];
|
||||
}
|
||||
|
||||
interface WalletAdapter {
|
||||
signAndSendTransaction(transaction: Transaction): Promise<{ signature: string }>;
|
||||
}
|
||||
|
||||
export async function sendSolanaTokenPayment(
|
||||
walletPublicKey: string,
|
||||
tokenAmount: BN,
|
||||
walletType: SolanaWalletType
|
||||
): Promise<SolanaPaymentResult> => {
|
||||
): Promise<SolanaPaymentResult> {
|
||||
try {
|
||||
const config = getSolanaConfig();
|
||||
let wallet: any = null;
|
||||
let wallet: WalletAdapter | null = null;
|
||||
|
||||
if (walletType === 'phantom') {
|
||||
wallet = window.phantom?.solana;
|
||||
wallet = window.phantom?.solana || null;
|
||||
} else if (walletType === 'solflare') {
|
||||
wallet = window.solflare;
|
||||
wallet = window.solflare || null;
|
||||
}
|
||||
|
||||
if (!wallet) {
|
||||
return {
|
||||
success: false,
|
||||
error: `${walletType} wallet not found`
|
||||
};
|
||||
throw new Error(`${walletType} wallet not found`);
|
||||
}
|
||||
|
||||
const connection = getConnection();
|
||||
const senderPublicKey = new PublicKey(walletPublicKey);
|
||||
const mintPublicKey = new PublicKey(config.tokenMintAddress);
|
||||
const receiverPublicKey = new PublicKey(config.tokenRecipientAddress);
|
||||
const mintPublicKey = new PublicKey(TOKEN_MINT);
|
||||
const receiverPublicKey = new PublicKey(PAYMENT_RECEIVER_ADDRESS);
|
||||
|
||||
console.log(`Processing ${config.tokenSymbol} payment with keys:`, {
|
||||
console.log('Processing payment with keys:', {
|
||||
sender: senderPublicKey.toBase58(),
|
||||
mint: mintPublicKey.toBase58(),
|
||||
receiver: receiverPublicKey.toBase58(),
|
||||
amount: config.paymentAmount,
|
||||
token: config.tokenSymbol
|
||||
});
|
||||
|
||||
// Get associated token addresses
|
||||
const senderATA = await getAssociatedTokenAddress(
|
||||
mintPublicKey,
|
||||
senderPublicKey
|
||||
const senderATA = await findAssociatedTokenAddress(
|
||||
senderPublicKey,
|
||||
mintPublicKey
|
||||
);
|
||||
|
||||
const receiverATA = await getAssociatedTokenAddress(
|
||||
mintPublicKey,
|
||||
receiverPublicKey
|
||||
const receiverATA = await findAssociatedTokenAddress(
|
||||
receiverPublicKey,
|
||||
mintPublicKey
|
||||
);
|
||||
|
||||
console.log('Token accounts:', {
|
||||
@ -161,8 +167,7 @@ export const sendSolanaTokenPayment = async (
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate amount in smallest units (considering decimals)
|
||||
const amountToSend = BigInt(config.paymentAmount * Math.pow(10, config.tokenDecimals));
|
||||
const amountToSend = BigInt(tokenAmount.toString());
|
||||
|
||||
// Add transfer instruction
|
||||
transaction.add(
|
||||
@ -179,7 +184,7 @@ export const sendSolanaTokenPayment = async (
|
||||
transaction.recentBlockhash = latestBlockhash.blockhash;
|
||||
transaction.feePayer = senderPublicKey;
|
||||
|
||||
console.log(`Sending ${config.tokenSymbol} payment transaction...`);
|
||||
console.log('Sending transaction...');
|
||||
const { signature } = await wallet.signAndSendTransaction(transaction);
|
||||
console.log('Transaction sent:', signature);
|
||||
|
||||
@ -200,7 +205,7 @@ export const sendSolanaTokenPayment = async (
|
||||
transactionSignature: signature
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Solana token payment error:', error);
|
||||
console.error('Payment error:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Payment failed'
|
||||
|
||||
@ -1,32 +1,18 @@
|
||||
import assert from 'assert';
|
||||
import BN from 'bn.js';
|
||||
import { Connection } from '@solana/web3.js';
|
||||
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
||||
import { getSolanaConfig } from '../config';
|
||||
|
||||
let connection: Connection | null = null;
|
||||
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
|
||||
|
||||
const getConnection = (): Connection => {
|
||||
if (!connection) {
|
||||
const config = getSolanaConfig();
|
||||
connection = new Connection(
|
||||
config.rpcUrl,
|
||||
{
|
||||
commitment: 'confirmed',
|
||||
confirmTransactionInitialTimeout: 60000,
|
||||
}
|
||||
);
|
||||
}
|
||||
return connection;
|
||||
};
|
||||
const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
|
||||
|
||||
interface SolanaTransactionInfo {
|
||||
authority: string;
|
||||
amount: string;
|
||||
}
|
||||
const connection = new Connection(SOLANA_RPC_URL);
|
||||
|
||||
const extractSolanaTransactionInfo = async (transactionSignature: string): Promise<SolanaTransactionInfo> => {
|
||||
const connection = getConnection();
|
||||
// Simplified transaction info extraction following reference implementation
|
||||
const extractTxInfo = async (transactionSignature: string): Promise<{ authority: string; amount: string }> => {
|
||||
const result = await connection.getParsedTransaction(transactionSignature, 'confirmed');
|
||||
|
||||
|
||||
if (!result) {
|
||||
throw new Error('Transaction not found');
|
||||
}
|
||||
@ -43,107 +29,6 @@ const extractSolanaTransactionInfo = async (transactionSignature: string): Promi
|
||||
return { authority, amount };
|
||||
};
|
||||
|
||||
export const verifySolanaPayment = async (
|
||||
transactionSignature: string
|
||||
): Promise<{
|
||||
valid: boolean,
|
||||
reason?: string,
|
||||
amount?: string,
|
||||
sender?: string
|
||||
}> => {
|
||||
try {
|
||||
const config = getSolanaConfig();
|
||||
const requiredAmountInSmallestUnits = (config.paymentAmount * Math.pow(10, config.tokenDecimals)).toString();
|
||||
|
||||
const connection = getConnection();
|
||||
|
||||
// Fetch transaction details
|
||||
const transactionResult = await connection.getParsedTransaction(transactionSignature, 'confirmed');
|
||||
|
||||
if (!transactionResult) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Transaction not found on Solana blockchain'
|
||||
};
|
||||
}
|
||||
|
||||
// Check if transaction was successful
|
||||
if (transactionResult.meta?.err) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Transaction failed: ${JSON.stringify(transactionResult.meta.err)}`
|
||||
};
|
||||
}
|
||||
|
||||
// Check transaction timestamp (5-minute window)
|
||||
const txTimestamp = transactionResult.blockTime ? new Date(transactionResult.blockTime * 1000) : null;
|
||||
if (!txTimestamp) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Transaction timestamp not available'
|
||||
};
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const timeDiffMs = now.getTime() - txTimestamp.getTime();
|
||||
const timeWindowMs = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
if (timeDiffMs > timeWindowMs) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Transaction is older than 5 minutes (${Math.round(timeDiffMs / 60000)} minutes old)`
|
||||
};
|
||||
}
|
||||
|
||||
// Extract transaction info
|
||||
const { amount, authority } = await extractSolanaTransactionInfo(transactionSignature);
|
||||
|
||||
// Verify amount
|
||||
if (parseInt(amount) < parseInt(requiredAmountInSmallestUnits)) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Payment amount (${amount}) is less than required (${requiredAmountInSmallestUnits})`
|
||||
};
|
||||
}
|
||||
|
||||
// Verify recipient address by checking the transaction instructions
|
||||
let foundValidTransfer = false;
|
||||
|
||||
for (const instruction of transactionResult.transaction.message.instructions) {
|
||||
if ('parsed' in instruction && instruction.programId.equals(TOKEN_PROGRAM_ID)) {
|
||||
const parsed = instruction.parsed;
|
||||
if (parsed.type === 'transferChecked' || parsed.type === 'transfer') {
|
||||
const destination = parsed.info.destination;
|
||||
|
||||
// Verify both amount and destination address
|
||||
if (parsed.info.amount === amount && destination === config.tokenRecipientAddress) {
|
||||
foundValidTransfer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundValidTransfer) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Valid Solana token transfer not found in transaction'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
amount,
|
||||
sender: authority
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error verifying Solana payment:', error);
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Failed to verify transaction: ${error instanceof Error ? error.message : 'Unknown error'}`
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to track used signatures (simple in-memory store for now)
|
||||
const usedSignatures = new Set<string>();
|
||||
@ -157,28 +42,111 @@ export const markSignatureAsUsed = (transactionSignature: string): void => {
|
||||
};
|
||||
|
||||
export const verifyUnusedSolanaPayment = async (
|
||||
transactionSignature: string
|
||||
): Promise<{
|
||||
valid: boolean,
|
||||
transactionSignature: string,
|
||||
tokenAmount: BN
|
||||
): Promise<{
|
||||
valid: boolean,
|
||||
reason?: string,
|
||||
amount?: string,
|
||||
sender?: string
|
||||
}> => {
|
||||
// Check if signature is already used
|
||||
if (isSignatureUsed(transactionSignature)) {
|
||||
try {
|
||||
// Check if signature is already used
|
||||
if (isSignatureUsed(transactionSignature)) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Transaction signature has already been used'
|
||||
};
|
||||
}
|
||||
|
||||
// Fetch transaction details
|
||||
const transactionResult = await connection.getParsedTransaction(transactionSignature, 'confirmed');
|
||||
|
||||
if (!transactionResult) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Transaction not found on Solana blockchain'
|
||||
};
|
||||
}
|
||||
|
||||
// Check if transaction was successful
|
||||
if (transactionResult.meta?.err) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Transaction failed: ${JSON.stringify(transactionResult.meta.err)}`
|
||||
};
|
||||
}
|
||||
|
||||
// Check transaction timestamp (5-minute window)
|
||||
const txTimestamp = transactionResult.blockTime ? new Date(transactionResult.blockTime * 1000) : null;
|
||||
if (!txTimestamp) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Transaction timestamp not available'
|
||||
};
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const timeDiffMs = now.getTime() - txTimestamp.getTime();
|
||||
const timeWindowMs = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
if (timeDiffMs > timeWindowMs) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Transaction is older than 5 minutes (${Math.round(timeDiffMs / 60000)} minutes old)`
|
||||
};
|
||||
}
|
||||
|
||||
// Extract transaction info using simplified approach
|
||||
const { amount, authority } = await extractTxInfo(transactionSignature);
|
||||
|
||||
// Verify amount using BN comparison like in reference
|
||||
const transactionAmount = new BN(amount);
|
||||
if (transactionAmount.lt(tokenAmount)) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: `Payment amount (${amount}) is less than required (${tokenAmount.toString()})`
|
||||
};
|
||||
}
|
||||
|
||||
// Verify recipient address by checking the transaction instructions
|
||||
let foundValidTransfer = false;
|
||||
|
||||
for (const instruction of transactionResult.transaction.message.instructions) {
|
||||
if ('parsed' in instruction && instruction.programId.equals(TOKEN_PROGRAM_ID)) {
|
||||
const parsed = instruction.parsed;
|
||||
if (parsed.type === 'transferChecked' || parsed.type === 'transfer') {
|
||||
const destination = parsed.info.destination;
|
||||
|
||||
// Verify both amount and destination address
|
||||
if (parsed.info.amount === amount && destination === process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS) {
|
||||
foundValidTransfer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundValidTransfer) {
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Valid Solana token transfer not found in transaction'
|
||||
};
|
||||
}
|
||||
|
||||
// Mark signature as used
|
||||
markSignatureAsUsed(transactionSignature);
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
amount,
|
||||
sender: authority
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error verifying Solana payment:', error);
|
||||
return {
|
||||
valid: false,
|
||||
reason: 'Transaction signature has already been used'
|
||||
reason: `Failed to verify transaction: ${error instanceof Error ? error.message : 'Unknown error'}`
|
||||
};
|
||||
}
|
||||
|
||||
// Verify the payment
|
||||
const result = await verifySolanaPayment(transactionSignature);
|
||||
|
||||
// If valid, mark as used
|
||||
if (result.valid) {
|
||||
markSignatureAsUsed(transactionSignature);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user