Add api to create a lock

This commit is contained in:
AdityaSalunkhe21 2025-02-05 16:47:48 +05:30 committed by Adw8
parent b211e88441
commit acd60d3ca5
12 changed files with 7471 additions and 13 deletions

2
Anchor.toml Normal file
View File

@ -0,0 +1,2 @@
[provider]
cluster = "mainnet"

514
package-lock.json generated
View File

@ -8,9 +8,11 @@
"name": "solana-meme-generator",
"version": "0.1.0",
"dependencies": {
"@coral-xyz/anchor": "^0.30.1",
"@fal-ai/client": "^1.2.1",
"@google/generative-ai": "^0.21.0",
"@solana/spl-token": "^0.3.8",
"@pinata/sdk": "^2.1.0",
"@solana/spl-token": "^0.3.11",
"@solana/web3.js": "^1.78.4",
"big.js": "^6.2.2",
"bn.js": "^5.2.0",
@ -73,6 +75,64 @@
"@chainsafe/is-ip": "^2.0.1"
}
},
"node_modules/@coral-xyz/anchor": {
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.30.1.tgz",
"integrity": "sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ==",
"dependencies": {
"@coral-xyz/anchor-errors": "^0.30.1",
"@coral-xyz/borsh": "^0.30.1",
"@noble/hashes": "^1.3.1",
"@solana/web3.js": "^1.68.0",
"bn.js": "^5.1.2",
"bs58": "^4.0.1",
"buffer-layout": "^1.2.2",
"camelcase": "^6.3.0",
"cross-fetch": "^3.1.5",
"crypto-hash": "^1.3.0",
"eventemitter3": "^4.0.7",
"pako": "^2.0.3",
"snake-case": "^3.0.4",
"superstruct": "^0.15.4",
"toml": "^3.0.0"
},
"engines": {
"node": ">=11"
}
},
"node_modules/@coral-xyz/anchor-errors": {
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/@coral-xyz/anchor-errors/-/anchor-errors-0.30.1.tgz",
"integrity": "sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ==",
"engines": {
"node": ">=10"
}
},
"node_modules/@coral-xyz/anchor/node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"node_modules/@coral-xyz/anchor/node_modules/superstruct": {
"version": "0.15.5",
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz",
"integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ=="
},
"node_modules/@coral-xyz/borsh": {
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.30.1.tgz",
"integrity": "sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ==",
"dependencies": {
"bn.js": "^5.1.2",
"buffer-layout": "^1.2.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@solana/web3.js": "^1.68.0"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@ -638,6 +698,53 @@
"node": ">=10"
}
},
"node_modules/@pinata/sdk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@pinata/sdk/-/sdk-2.1.0.tgz",
"integrity": "sha512-hkS0tcKtsjf9xhsEBs2Nbey5s+Db7x5rlOH9TaWHBXkJ7IwwOs2xnEDigNaxAHKjYAwcw+m2hzpO5QgOfeF7Zw==",
"deprecated": "Please install the new IPFS SDK at pinata-web3. More information at https://docs.pinata.cloud/web3/sdk",
"dependencies": {
"axios": "^0.21.1",
"form-data": "^2.3.3",
"is-ipfs": "^0.6.0",
"path": "^0.12.7"
}
},
"node_modules/@pinata/sdk/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/@pinata/sdk/node_modules/form-data": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz",
"integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12",
"safe-buffer": "^5.2.1"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/@pinata/sdk/node_modules/is-ipfs": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/is-ipfs/-/is-ipfs-0.6.3.tgz",
"integrity": "sha512-HyRot1dvLcxImtDqPxAaY1miO6WsiP/z7Yxpg2qpaLWv5UdhAPtLvHJ4kMLM0w8GSl8AFsVF23PHe1LzuWrUlQ==",
"dependencies": {
"bs58": "^4.0.1",
"cids": "~0.7.0",
"mafmt": "^7.0.0",
"multiaddr": "^7.2.1",
"multibase": "~0.6.0",
"multihashes": "~0.4.13"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -1763,6 +1870,14 @@
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-layout": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz",
"integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==",
"engines": {
"node": ">=4.5"
}
},
"node_modules/bufferutil": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz",
@ -1872,6 +1987,17 @@
"node": ">=6"
}
},
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@ -1955,6 +2081,51 @@
"node": ">=10"
}
},
"node_modules/cids": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz",
"integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"buffer": "^5.5.0",
"class-is": "^1.1.0",
"multibase": "~0.6.0",
"multicodec": "^1.0.0",
"multihashes": "~0.4.15"
},
"engines": {
"node": ">=4.0.0",
"npm": ">=3.0.0"
}
},
"node_modules/cids/node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/class-is": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz",
"integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw=="
},
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@ -2125,6 +2296,14 @@
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"devOptional": true
},
"node_modules/cross-fetch": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
"integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
"dependencies": {
"node-fetch": "^2.7.0"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -2138,6 +2317,17 @@
"node": ">= 8"
}
},
"node_modules/crypto-hash": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz",
"integrity": "sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@ -2393,6 +2583,15 @@
"node": ">=6.0.0"
}
},
"node_modules/dot-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/dotenv": {
"version": "16.4.7",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
@ -3992,6 +4191,14 @@
"node": ">= 12"
}
},
"node_modules/ip-regex": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
"integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@ -4202,6 +4409,17 @@
"node": ">=0.10.0"
}
},
"node_modules/is-ip": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz",
"integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==",
"dependencies": {
"ip-regex": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-ipfs": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/is-ipfs/-/is-ipfs-8.0.4.tgz",
@ -4714,6 +4932,14 @@
"loose-envify": "cli.js"
}
},
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@ -4726,6 +4952,14 @@
"node": ">=10"
}
},
"node_modules/mafmt": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/mafmt/-/mafmt-7.1.0.tgz",
"integrity": "sha512-vpeo9S+hepT3k2h5iFxzEHvvR0GPBx9uKaErmnRzYNcaKb03DgOArjEMlgG4a9LcuZZ89a3I8xbeto487n26eA==",
"dependencies": {
"multiaddr": "^7.3.0"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@ -4949,11 +5183,226 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/multiaddr": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-7.5.0.tgz",
"integrity": "sha512-GvhHsIGDULh06jyb6ev+VfREH9evJCFIRnh3jUt9iEZ6XDbyoisZRFEI9bMvK/AiR6y66y6P+eoBw9mBYMhMvw==",
"deprecated": "This module is deprecated, please upgrade to @multiformats/multiaddr",
"dependencies": {
"buffer": "^5.5.0",
"cids": "~0.8.0",
"class-is": "^1.1.0",
"is-ip": "^3.1.0",
"multibase": "^0.7.0",
"varint": "^5.0.0"
}
},
"node_modules/multiaddr/node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/multiaddr/node_modules/cids": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/cids/-/cids-0.8.3.tgz",
"integrity": "sha512-yoXTbV3llpm+EBGWKeL9xKtksPE/s6DPoDSY4fn8I8TEW1zehWXPSB0pwAXVDlLaOlrw+sNynj995uD9abmPhA==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"buffer": "^5.6.0",
"class-is": "^1.1.0",
"multibase": "^1.0.0",
"multicodec": "^1.0.1",
"multihashes": "^1.0.1"
},
"engines": {
"node": ">=4.0.0",
"npm": ">=3.0.0"
}
},
"node_modules/multiaddr/node_modules/cids/node_modules/multibase": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/multibase/-/multibase-1.0.1.tgz",
"integrity": "sha512-KcCxpBVY8fdVKu4dJMAahq4F/2Z/9xqEjIiR7PiMe7LRGeorFn2NLmicN6nLBCqQvft6MG2Lc9X5P0IdyvnxEw==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"base-x": "^3.0.8",
"buffer": "^5.5.0"
},
"engines": {
"node": ">=10.0.0",
"npm": ">=6.0.0"
}
},
"node_modules/multiaddr/node_modules/multibase": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz",
"integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"base-x": "^3.0.8",
"buffer": "^5.5.0"
}
},
"node_modules/multiaddr/node_modules/multihashes": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-1.0.1.tgz",
"integrity": "sha512-S27Tepg4i8atNiFaU5ZOm3+gl3KQlUanLs/jWcBxQHFttgq+5x1OgbQmf2d8axJ/48zYGBd/wT9d723USMFduw==",
"dependencies": {
"buffer": "^5.6.0",
"multibase": "^1.0.1",
"varint": "^5.0.0"
},
"engines": {
"node": ">=10.0.0",
"npm": ">=6.0.0"
}
},
"node_modules/multiaddr/node_modules/multihashes/node_modules/multibase": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/multibase/-/multibase-1.0.1.tgz",
"integrity": "sha512-KcCxpBVY8fdVKu4dJMAahq4F/2Z/9xqEjIiR7PiMe7LRGeorFn2NLmicN6nLBCqQvft6MG2Lc9X5P0IdyvnxEw==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"base-x": "^3.0.8",
"buffer": "^5.5.0"
},
"engines": {
"node": ">=10.0.0",
"npm": ">=6.0.0"
}
},
"node_modules/multibase": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz",
"integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"base-x": "^3.0.8",
"buffer": "^5.5.0"
}
},
"node_modules/multibase/node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/multicodec": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz",
"integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"buffer": "^5.6.0",
"varint": "^5.0.0"
}
},
"node_modules/multicodec/node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/multiformats": {
"version": "13.3.1",
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.3.1.tgz",
"integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g=="
},
"node_modules/multihashes": {
"version": "0.4.21",
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz",
"integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==",
"dependencies": {
"buffer": "^5.5.0",
"multibase": "^0.7.0",
"varint": "^5.0.0"
}
},
"node_modules/multihashes/node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/multihashes/node_modules/multibase": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz",
"integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==",
"deprecated": "This module has been superseded by the multiformats module",
"dependencies": {
"base-x": "^3.0.8",
"buffer": "^5.5.0"
}
},
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@ -5073,6 +5522,15 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node_modules/node-abi": {
"version": "3.74.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
@ -5498,6 +5956,11 @@
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
},
"node_modules/pako": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -5528,6 +5991,15 @@
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/path": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
"dependencies": {
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -5864,6 +6336,14 @@
"node": ">= 0.8.0"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/progress-events": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.1.tgz",
@ -6551,6 +7031,15 @@
"npm": ">= 3.0.0"
}
},
"node_modules/snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/socks": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
@ -7112,6 +7601,11 @@
"node": ">=8.0"
}
},
"node_modules/toml": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@ -7646,11 +8140,24 @@
"node": ">=6.14.2"
}
},
"node_modules/util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"dependencies": {
"inherits": "2.0.3"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/util/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
@ -7665,6 +8172,11 @@
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"devOptional": true
},
"node_modules/varint": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
"integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",

View File

@ -9,9 +9,11 @@
"lint": "next lint"
},
"dependencies": {
"@coral-xyz/anchor": "^0.30.1",
"@fal-ai/client": "^1.2.1",
"@google/generative-ai": "^0.21.0",
"@solana/spl-token": "^0.3.8",
"@pinata/sdk": "^2.1.0",
"@solana/spl-token": "^0.3.11",
"@solana/web3.js": "^1.78.4",
"big.js": "^6.2.2",
"bn.js": "^5.2.0",

View File

@ -88,6 +88,7 @@ export async function POST(req: NextRequest): Promise<NextResponse> {
// Extract the image URL from the response
const imageUrl = result.data?.images?.[0]?.url
console.log(imageUrl);
if (!imageUrl) {
console.error('No image URL in response:', result)

172
src/app/api/lock/route.ts Normal file
View File

@ -0,0 +1,172 @@
import { NextRequest, NextResponse } from "next/server";
import { Connection, Keypair, ParsedInstruction, ParsedTransactionWithMeta, PartiallyDecodedInstruction, PublicKey } from "@solana/web3.js";
import { createLock } from "../../../utils/create-lock";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import assert from "assert";
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
import { BN, min } from "bn.js";
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL);
const connection = new Connection(process.env.NEXT_PUBLIC_SOLANA_RPC_URL);
const MTM_MINT_ADDRESS = process.env.NEXT_PUBLIC_MTM_TOKEN_MINT;
function isParsedInstruction(
instruction: ParsedInstruction | PartiallyDecodedInstruction
): instruction is ParsedInstruction {
return (instruction as ParsedInstruction).parsed !== undefined;
}
async function extractMTMTransferDetails(
connection: Connection,
signature: string,
mtmMintAddress: string // Mint address of the MTM token
) {
try {
// Fetch the transaction details using the signature
const transaction: ParsedTransactionWithMeta | null = await connection.getParsedTransaction(signature, {
maxSupportedTransactionVersion: 0, // Ensure compatibility with legacy transactions
});
if (!transaction) {
throw new Error('Transaction not found');
}
// Extract the "from", "to", and "amount" for the MTM token transfer
let fromAddress: string | null = null;
let toAddress: string | null = null;
let tokenAmount: number | null = null;
// Function to process instructions
const processInstructions = (instructions: ParsedInstruction[]) => {
instructions.forEach((instruction: ParsedInstruction) => {
if (instruction.programId.equals(new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'))) {
// Check if the instruction is a transfer instruction
if (instruction.parsed.type === 'transfer' || instruction.parsed.type === 'transferChecked') {
const parsedInfo = instruction.parsed.info;
const mint = parsedInfo.mint;
// Check if the mint address matches the provided MTM mint address
if (mint === mtmMintAddress) {
fromAddress = parsedInfo.source;
toAddress = parsedInfo.destination;
tokenAmount = parsedInfo.amount;
}
}
}
});
};
// Filter out PartiallyDecodedInstruction and process only ParsedInstruction
const parsedInstructions = transaction.transaction.message.instructions.filter(isParsedInstruction);
// Process top-level instructions
processInstructions(parsedInstructions);
// Process inner instructions (if any)
if (transaction.meta?.innerInstructions) {
transaction.meta.innerInstructions.forEach((inner) => {
const innerParsedInstructions = inner.instructions.filter(isParsedInstruction);
processInstructions(innerParsedInstructions);
});
}
if (!fromAddress || !toAddress || !tokenAmount) {
throw new Error('No matching MTM token transfer found in the transaction');
}
return { fromAddress, toAddress, tokenAmount };
} catch (error) {
console.error('Error extracting MTM transfer details:', error);
throw error;
}
}
export async function GET(req: NextRequest) {
try {
// Get signature from URL params
const { searchParams } = new URL(req.url);
const signature = searchParams.get('signature') || '4HBtnoNUuMGpmbhD9cPiJtbxkhux31pfZs3HYud5eopAU69RaC4UbJsYdj83eafFxV6eH8pSaRgqELrwyjrWp7yz';
let amount = new BN(0);
if (!signature) {
return NextResponse.json(
{ error: "Transaction signature is required" },
{ status: 400 }
);
}
if (!MTM_MINT_ADDRESS) {
return NextResponse.json(
{ error: "MTM_MINT_ADDRESS environment variable is not set" },
{ status: 500 }
);
}
// Extract transaction details
// const result = await extractMTMTransferDetails(
// connection,
// signature,
// MTM_MINT_ADDRESS
// );
// if (!result) {
// return NextResponse.json(
// { error: "Failed to extract transaction details" },
// { status: 500 }
// );
// }
// console.log({ result });
// // Validate extracted values
// if (!result.fromAddress || result.tokenAmount <= 0) {
// return NextResponse.json(
// { error: "Invalid transaction details extracted" },
// { status: 400 }
// );
// }
assert(process.env.USER_PRIVATE_KEY, 'USER_PRIVATE_KEY is required');
assert(process.env.CLIFF_TIME, 'CLIFF_TIME is required');
const USER_PRIVATE_KEY = process.env.USER_PRIVATE_KEY;
const CLIFF_TIME = process.env.CLIFF_TIME;
const duration = new BN(CLIFF_TIME).add(new BN(Math.floor(Date.now() / 1000)));
const tokenLockerKeypair = Keypair.fromSecretKey(bs58.decode(USER_PRIVATE_KEY));
const recipientPublicKey = new PublicKey('Bnnq8n3rRKZe8NJAYn4vBkxp1v8Bnc6zXpUPpDeujCu');
amount = amount.add(new BN(1000000));
// Call createLock function with extracted values
let escrow;
try {
escrow = await createLock(tokenLockerKeypair, recipientPublicKey, duration, amount);
} catch (error) {
console.error('Error creating lock:', error);
return NextResponse.json(
{ error: "Failed to create lock" },
{ status: 500 }
);
}
console.log({ escrow });
// Return successful response
return NextResponse.json({
success: true,
data: {
sender: recipientPublicKey,
amount: amount,
}
});
} catch (error) {
console.error('API route error:', error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}

254
src/locker-utils/index.ts Normal file
View File

@ -0,0 +1,254 @@
/**
* Methods from jup-lock:
* - createLockerProgram
* - deriveEscrow
* - createVestingPlanV2
* Reference: https://github.com/jup-ag/jup-lock/blob/main/tests/locker_utils/index.ts
*/
import assert from 'assert';
import 'dotenv/config';
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddressSync,
TOKEN_2022_PROGRAM_ID,
TOKEN_PROGRAM_ID,
} from '@solana/spl-token';
import {
AnchorProvider,
BN,
Program,
Wallet,
web3,
workspace,
} from '@coral-xyz/anchor';
import { AccountMeta, Connection, SendTransactionError } from '@solana/web3.js';
// TODO: Generate type file from IDL json
import { Locker } from '../../target/types/locker';
import { TokenExtensionUtil } from './token-2022/token-extensions';
import {
OptionRemainingAccountsInfoData,
RemainingAccountsBuilder,
RemainingAccountsType,
} from './token-2022/remaining-accounts';
assert(process.env.RPC_ENDPOINT);
const connection = new Connection(process.env.RPC_ENDPOINT);
const ESCROW_USE_SPL_TOKEN = 0;
const MEMO_PROGRAM = new web3.PublicKey(
"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
);
export function createLockerProgram(wallet: Wallet): Program<Locker> {
const provider = new AnchorProvider(connection, wallet, {
maxRetries: 3,
});
provider.opts.commitment = 'confirmed';
return workspace.Locker as Program<Locker>;
}
export function deriveEscrow(base: web3.PublicKey, programId: web3.PublicKey) {
return web3.PublicKey.findProgramAddressSync(
[Buffer.from('escrow'), base.toBuffer()],
programId
);
}
export interface CreateVestingPlanParams {
ownerKeypair: web3.Keypair;
tokenMint: web3.PublicKey;
isAssertion: boolean;
vestingStartTime: BN;
cliffTime: BN;
frequency: BN;
cliffUnlockAmount: BN;
amountPerPeriod: BN;
numberOfPeriod: BN;
recipient: web3.PublicKey;
updateRecipientMode: number;
cancelMode: number;
tokenProgram?: web3.PublicKey;
}
// V2 instructions
export async function createVestingPlanV2(params: CreateVestingPlanParams) {
let {
tokenMint,
ownerKeypair,
vestingStartTime,
cliffTime,
frequency,
cliffUnlockAmount,
amountPerPeriod,
numberOfPeriod,
recipient,
updateRecipientMode,
cancelMode,
tokenProgram,
} = params;
const program = createLockerProgram(new Wallet(ownerKeypair));
const baseKP = web3.Keypair.generate();
let [escrow] = deriveEscrow(baseKP.publicKey, program.programId);
const senderToken = getAssociatedTokenAddressSync(
tokenMint,
ownerKeypair.publicKey,
false,
tokenProgram,
ASSOCIATED_TOKEN_PROGRAM_ID
);
const escrowToken = getAssociatedTokenAddressSync(
tokenMint,
escrow,
true,
tokenProgram,
ASSOCIATED_TOKEN_PROGRAM_ID
);
let remainingAccountsInfo = null;
let remainingAccounts: AccountMeta[] = [];
if (tokenProgram == TOKEN_2022_PROGRAM_ID) {
let inputTransferHookAccounts =
await TokenExtensionUtil.getExtraAccountMetasForTransferHook(
program.provider.connection,
tokenMint,
senderToken,
escrowToken,
ownerKeypair.publicKey,
TOKEN_2022_PROGRAM_ID
);
[remainingAccountsInfo, remainingAccounts] = new RemainingAccountsBuilder()
.addSlice(
RemainingAccountsType.TransferHookEscrow,
inputTransferHookAccounts
)
.build() as [OptionRemainingAccountsInfoData, AccountMeta[]];
}
assert(tokenProgram);
try {
const transaction = await program.methods
.createVestingEscrowV2(
{
vestingStartTime,
cliffTime,
frequency,
cliffUnlockAmount,
amountPerPeriod,
numberOfPeriod,
updateRecipientMode,
cancelMode,
},
remainingAccountsInfo
)
.accounts({
base: baseKP.publicKey,
senderToken,
escrowToken,
recipient,
tokenMint,
sender: ownerKeypair.publicKey,
tokenProgram,
systemProgram: web3.SystemProgram.programId,
escrow,
// TODO: Fix type error for escrowToken
} as any)
.remainingAccounts(remainingAccounts ? remainingAccounts : [])
.preInstructions([
createAssociatedTokenAccountInstruction(
ownerKeypair.publicKey,
escrowToken,
escrow,
tokenMint,
tokenProgram,
ASSOCIATED_TOKEN_PROGRAM_ID
),
])
.signers([baseKP, ownerKeypair])
.rpc();
return escrow;
} catch (error) {
if (error instanceof SendTransactionError) {
console.error('Transaction failed:', error.message);
console.error('Logs:', error.logs);
}
throw error;
}
}
export interface ClaimTokenParamsV2 {
isAssertion: boolean;
escrow: web3.PublicKey;
recipient: web3.Keypair;
maxAmount: BN;
recipientToken: web3.PublicKey;
tokenProgram: web3.PublicKey;
}
export async function claimTokenV2(params: ClaimTokenParamsV2) {
let { isAssertion, escrow, recipient, maxAmount, recipientToken } = params;
const program = createLockerProgram(new Wallet(recipient));
const escrowState = await program.account.vestingEscrow.fetch(escrow);
const tokenProgram =
escrowState.tokenProgramFlag == ESCROW_USE_SPL_TOKEN
? TOKEN_PROGRAM_ID
: TOKEN_2022_PROGRAM_ID;
const escrowToken = getAssociatedTokenAddressSync(
escrowState.tokenMint,
escrow,
true,
tokenProgram,
ASSOCIATED_TOKEN_PROGRAM_ID
);
let remainingAccountsInfo = null;
let remainingAccounts: AccountMeta[] | undefined = [];
if (tokenProgram == TOKEN_2022_PROGRAM_ID) {
let claimTransferHookAccounts =
await TokenExtensionUtil.getExtraAccountMetasForTransferHook(
program.provider.connection,
escrowState.tokenMint,
escrowToken,
recipientToken,
escrow,
TOKEN_2022_PROGRAM_ID
);
[remainingAccountsInfo, remainingAccounts] = new RemainingAccountsBuilder()
.addSlice(
RemainingAccountsType.TransferHookEscrow,
claimTransferHookAccounts
)
.build();
}
const tx = await program.methods
.claimV2(maxAmount, remainingAccountsInfo)
.accounts({
tokenProgram,
tokenMint: escrowState.tokenMint,
memoProgram: MEMO_PROGRAM,
escrow,
escrowToken,
recipient: recipient.publicKey,
recipientToken,
} as any)
.remainingAccounts(remainingAccounts ? remainingAccounts : [])
.signers([recipient])
.rpc();
}

View File

@ -0,0 +1,50 @@
// Reference: https://github.com/jup-ag/jup-lock/blob/main/tests/locker_utils/index.ts
import { AccountMeta } from '@solana/web3.js';
export enum RemainingAccountsType {
TransferHookEscrow = 'transferHookEscrow',
}
type RemainingAccountsAnchorType = { transferHookEscrow: {} };
export type RemainingAccountsSliceData = {
accountsType: RemainingAccountsAnchorType;
length: number;
};
export type RemainingAccountsInfoData = {
slices: RemainingAccountsSliceData[];
};
// Option<RemainingAccountsInfoData> on Rust
// null is treated as None in Rust. undefined doesn't work.
export type OptionRemainingAccountsInfoData = RemainingAccountsInfoData | null;
export class RemainingAccountsBuilder {
private remainingAccounts: AccountMeta[] = [];
private slices: RemainingAccountsSliceData[] = [];
constructor() {}
addSlice(
accountsType: RemainingAccountsType,
accounts?: AccountMeta[]
): this {
if (!accounts || accounts.length === 0) return this;
this.slices.push({
accountsType: { [accountsType]: {} } as RemainingAccountsAnchorType,
length: accounts.length,
});
this.remainingAccounts.push(...accounts);
return this;
}
build(): [OptionRemainingAccountsInfoData, AccountMeta[] | undefined] {
return this.slices.length === 0
? [null, undefined]
: [{ slices: this.slices }, this.remainingAccounts];
}
}

View File

@ -0,0 +1,57 @@
// Reference: https://github.com/jup-ag/jup-lock/blob/main/tests/locker_utils/index.ts
import {
AccountMeta,
Connection,
PublicKey,
TransactionInstruction,
} from '@solana/web3.js';
import {
addExtraAccountsToInstruction,
getMint,
getTransferHook,
TOKEN_2022_PROGRAM_ID,
} from '@solana/spl-token';
export class TokenExtensionUtil {
public static async getExtraAccountMetasForTransferHook(
connection: Connection,
tokenMint: PublicKey,
source: PublicKey,
destination: PublicKey,
owner: PublicKey,
tokenProgram: PublicKey
): Promise<AccountMeta[] | undefined> {
let mint = await getMint(connection, tokenMint, 'confirmed', tokenProgram);
const transferHook = getTransferHook(mint);
if (!transferHook) return undefined;
const instruction = new TransactionInstruction({
programId: TOKEN_2022_PROGRAM_ID,
keys: [
{ pubkey: source, isSigner: false, isWritable: false },
{
pubkey: tokenMint,
isSigner: false,
isWritable: false,
},
{ pubkey: destination, isSigner: false, isWritable: false },
{ pubkey: owner, isSigner: false, isWritable: false },
{ pubkey: owner, isSigner: false, isWritable: false },
],
});
// Note:
await addExtraAccountsToInstruction(
connection,
instruction,
tokenMint,
'confirmed',
transferHook.programId,
);
const extraAccountMetas = instruction.keys.slice(5);
return extraAccountMetas.length > 0 ? extraAccountMetas : undefined;
}
}

95
src/utils/create-lock.ts Normal file
View File

@ -0,0 +1,95 @@
import assert from 'assert';
import BN from 'bn.js';
import 'dotenv/config';
import bs58 from 'bs58';
import * as anchor from "@coral-xyz/anchor";
import {
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import { Connection, PublicKey } from "@solana/web3.js";
import { createVestingPlanV2 } from '../locker-utils';
assert(process.env.RPC_ENDPOINT);
assert(process.env.USER_PRIVATE_KEY);
//assert(process.env.RECIPIENT_PUBLIC_KEY);
assert(process.env.MTM_MINT);
const RPC_ENDPOINT= process.env.RPC_ENDPOINT;
const MTM_MINT = process.env.MTM_MINT;
const USER_PRIVATE_KEY = process.env.USER_PRIVATE_KEY;
const userKP = anchor.web3.Keypair.fromSecretKey(bs58.decode(USER_PRIVATE_KEY));
const connection = new Connection(RPC_ENDPOINT);
const token = new PublicKey(MTM_MINT);
const provider = new anchor.AnchorProvider(
connection,
new anchor.Wallet(userKP),
// Commitment level required for simulating transaction
{ preflightCommitment: 'processed' }
);
anchor.setProvider(provider);
export async function getMTMBalance (senderKeypair: anchor.web3.Keypair): Promise<BN> {
const mintPublicKey = new PublicKey(MTM_MINT);
const publicKey = senderKeypair.publicKey;
const tokenAccounts = await connection.getTokenAccountsByOwner(publicKey, { mint: mintPublicKey });
let balance = new BN(0);
for (const tokenAccount of tokenAccounts.value) {
const accountInfo = await connection.getParsedAccountInfo(
tokenAccount.pubkey,
"confirmed"
);
if (!accountInfo.value || Buffer.isBuffer(accountInfo.value.data)) {
console.warn(
`Token account ${tokenAccount.pubkey.toBase58()} data is not parsed.`
);
continue;
}
const tokenAmount =
(accountInfo.value.data as any).parsed?.info?.tokenAmount?.amount || "0";
balance = balance.add(new BN(tokenAmount));
}
return balance;
};
export async function createLock(tokenLockerKeypair: anchor.web3.Keypair, recipientPubKey: anchor.web3.PublicKey, duration: BN, balance: BN): Promise<anchor.web3.PublicKey | void> {
//const balance = await getMTMBalance(tokenLockerKeypair);
if (balance.eq(new BN(0))) {
console.log('No balance available to create lock, skipping...');
return;
}
console.log('Creating a lock...');
const escrow = await createVestingPlanV2({
ownerKeypair: tokenLockerKeypair,
vestingStartTime: new BN(Math.floor(Date.now() / 1000) - 60), // Start immediately
tokenMint: token,
isAssertion: true,
cliffTime: duration,
frequency: new BN(1), // Not needed since full unlock happens at cliff
cliffUnlockAmount: balance, // The entire amount should be released at cliff
amountPerPeriod: new BN(0), // No tokens should be released before cliff
numberOfPeriod: new BN(1), // Only release tokens once
recipient: recipientPubKey,
updateRecipientMode: 0,
cancelMode: 1,
tokenProgram: TOKEN_PROGRAM_ID,
});
if (escrow) {
console.log('Lock created successfully: ', escrow.toString());
}
return escrow;
}

View File

@ -1,28 +1,49 @@
import { PinataSDK } from 'pinata-web3';
import PinataClient from "@pinata/sdk"
import 'dotenv/config';
import assert from 'assert';
import { FluxGenerationResult } from '../services/fluxService';
import axios from 'axios';
import FormData from 'form-data';
assert(process.env.PINATA_JWT, "PINATA_JWT is required");
assert(process.env.PINATA_GATEWAY, "PINATA_GATEWAY is required");
assert(process.env.PINATA_API_KEY, "PINATA_API_KEY is required");
assert(process.env.PINATA_SECRET_KEY, "PINATA_SECRET_KEY is required");
assert(process.env.PINATA_JWT, "PINATA_SECRET_KEY is required");
assert(process.env.PINATA_GATEWAY);
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT,
pinataGateway: process.env.PINATA_GATEWAY,
const pinata = new PinataClient({
pinataApiKey: process.env.PINATA_API_KEY,
pinataSecretApiKey: process.env.PINATA_SECRET_KEY,
pinataJWTKey: process.env.PINATA_JWT
});
export async function uploadToPinata(imageUrl: string): Promise<FluxGenerationResult> {
try {
const upload = await pinata.upload.url(imageUrl);
const response = await axios.get(imageUrl, {
responseType: 'arraybuffer'
});
const publicURL = await pinata.gateways.convert(upload.IpfsHash);
// Create form data
const formData = new FormData();
formData.append('file', Buffer.from(response.data), {
filename: `image-${Date.now()}.jpg`,
contentType: 'image/jpeg',
});
// Use the correct Pinata method for file upload
const result = await pinata.pinFileToIPFS(formData);
if (!result.IpfsHash) {
throw new Error('IPFS hash not received from Pinata');
}
const publicURL = `${process.env.PINATA_GATEWAY}/ipfs/${result.IpfsHash}`;
return { imageUrl: publicURL };
} catch (error) {
console.error('Error uploading to Pinata:', error)
console.error('Error uploading to Pinata:', error);
return {
error: error instanceof Error ? error.message : 'Upload failed'
};
}
}
}

3143
target/idl/locker.json Normal file

File diff suppressed because it is too large Load Diff

3149
target/types/locker.ts Normal file

File diff suppressed because it is too large Load Diff