forked from mito-systems/sol-mem-gen
bunch of stuff
This commit is contained in:
parent
1a9869b0d9
commit
aeb240cfc5
175
package-lock.json
generated
175
package-lock.json
generated
@ -9,9 +9,11 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fal-ai/client": "^1.2.1",
|
"@fal-ai/client": "^1.2.1",
|
||||||
|
"@google/generative-ai": "^0.21.0",
|
||||||
"@solana/spl-token": "^0.3.8",
|
"@solana/spl-token": "^0.3.8",
|
||||||
"@solana/web3.js": "^1.78.4",
|
"@solana/web3.js": "^1.78.4",
|
||||||
"next": "13.5.4",
|
"next": "13.5.4",
|
||||||
|
"openai": "^4.77.0",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -144,6 +146,14 @@
|
|||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@google/generative-ai": {
|
||||||
|
"version": "0.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.21.0.tgz",
|
||||||
|
"integrity": "sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.14",
|
"version": "0.11.14",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||||
@ -752,6 +762,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz",
|
||||||
"integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA=="
|
"integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node-fetch": {
|
||||||
|
"version": "2.6.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||||
|
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"form-data": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.14",
|
"version": "15.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
|
||||||
@ -900,6 +919,17 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/abort-controller": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||||
|
"dependencies": {
|
||||||
|
"event-target-shim": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||||
@ -1176,6 +1206,11 @@
|
|||||||
"integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
|
"integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
|
},
|
||||||
"node_modules/autoprefixer": {
|
"node_modules/autoprefixer": {
|
||||||
"version": "10.4.15",
|
"version": "10.4.15",
|
||||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz",
|
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz",
|
||||||
@ -1596,6 +1631,17 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "12.1.0",
|
"version": "12.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||||
@ -1767,6 +1813,14 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/didyoumean": {
|
"node_modules/didyoumean": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||||
@ -2567,6 +2621,14 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/event-target-shim": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eventemitter3": {
|
"node_modules/eventemitter3": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||||
@ -2744,6 +2806,36 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/form-data-encoder": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
|
||||||
|
},
|
||||||
|
"node_modules/formdata-node": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "1.0.0",
|
||||||
|
"web-streams-polyfill": "4.0.0-beta.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fraction.js": {
|
"node_modules/fraction.js": {
|
||||||
"version": "4.3.7",
|
"version": "4.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||||
@ -3888,6 +3980,25 @@
|
|||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.3",
|
"version": "9.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||||
@ -4005,6 +4116,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
@ -4191,6 +4320,39 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/openai": {
|
||||||
|
"version": "4.77.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/openai/-/openai-4.77.0.tgz",
|
||||||
|
"integrity": "sha512-WWacavtns/7pCUkOWvQIjyOfcdr9X+9n9Vvb0zFeKVDAqwCMDHB+iSr24SVaBAhplvSG6JrRXFpcNM9gWhOGIw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"@types/node-fetch": "^2.6.4",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"agentkeepalive": "^4.2.1",
|
||||||
|
"form-data-encoder": "1.7.2",
|
||||||
|
"formdata-node": "^4.3.2",
|
||||||
|
"node-fetch": "^2.6.7"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"openai": "bin/cli"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.23.8"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"zod": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/openai/node_modules/@types/node": {
|
||||||
|
"version": "18.19.68",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz",
|
||||||
|
"integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~5.26.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
@ -5649,6 +5811,11 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "5.26.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||||
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
|
||||||
@ -5727,6 +5894,14 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "4.0.0-beta.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
|
||||||
|
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
@ -10,9 +10,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fal-ai/client": "^1.2.1",
|
"@fal-ai/client": "^1.2.1",
|
||||||
|
"@google/generative-ai": "^0.21.0",
|
||||||
"@solana/spl-token": "^0.3.8",
|
"@solana/spl-token": "^0.3.8",
|
||||||
"@solana/web3.js": "^1.78.4",
|
"@solana/web3.js": "^1.78.4",
|
||||||
"next": "13.5.4",
|
"next": "13.5.4",
|
||||||
|
"openai": "^4.77.0",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
|
65
src/app/api/adobe/route.ts
Normal file
65
src/app/api/adobe/route.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
|
if (!process.env.ADOBE_API_KEY || !process.env.ADOBE_CLIENT_SECRET) {
|
||||||
|
throw new Error('Adobe API credentials not configured')
|
||||||
|
}
|
||||||
|
|
||||||
|
const ADOBE_API_URL = 'https://firefly-api.adobe.io
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest): Promise<NextResponse> {
|
||||||
|
try {
|
||||||
|
const { prompt } = await req.json()
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Prompt is required' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adobe Firefly API request
|
||||||
|
const response = await fetch(ADOBE_API_URL, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'x-api-key': process.env.ADOBE_API_KEY,
|
||||||
|
'Authorization': `Bearer ${process.env.ADOBE_API_KEY}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: prompt,
|
||||||
|
n: 1,
|
||||||
|
size: { width: 1024, height: 1024 },
|
||||||
|
styles: ["default"],
|
||||||
|
seed: Math.floor(Math.random() * 1000000),
|
||||||
|
quality: "standard",
|
||||||
|
contentClass: "photo"
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json()
|
||||||
|
console.error('Adobe API error:', errorData)
|
||||||
|
throw new Error(`Adobe API error: ${response.status}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
console.log('Adobe generation result:', data)
|
||||||
|
|
||||||
|
// Extract the image URL from the response
|
||||||
|
const imageUrl = data.outputs?.[0]?.image
|
||||||
|
|
||||||
|
if (!imageUrl) {
|
||||||
|
throw new Error('No image URL in response')
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ imageUrl })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Adobe generation error:', error)
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: error instanceof Error ? error.message : 'Failed to generate image' },
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const dynamic = 'force-dynamic'
|
37
src/app/api/gemini/route.ts
Normal file
37
src/app/api/gemini/route.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { GoogleGenerativeAI } from '@google/generative-ai'
|
||||||
|
|
||||||
|
if (!process.env.GEMINI_API_KEY) {
|
||||||
|
throw new Error('GEMINI_API_KEY is not configured in environment variables')
|
||||||
|
}
|
||||||
|
|
||||||
|
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY)
|
||||||
|
const model = genAI.getGenerativeModel({ model: "gemini-1.5-pro" })
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest): Promise<NextResponse> {
|
||||||
|
try {
|
||||||
|
const { prompt } = await req.json()
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Prompt is required' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await model.generateContent(prompt)
|
||||||
|
const response = await result.response
|
||||||
|
const text = response.text()
|
||||||
|
|
||||||
|
console.log('Gemini generation result:', text)
|
||||||
|
return NextResponse.json({ response: text })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Gemini generation error:', error)
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: error instanceof Error ? error.message : 'Failed to generate text' },
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const dynamic = 'force-dynamic'
|
47
src/app/api/grok/route.ts
Normal file
47
src/app/api/grok/route.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import OpenAI from "openai";
|
||||||
|
|
||||||
|
if (!process.env.XAI_API_KEY) {
|
||||||
|
throw new Error('XAI_API_KEY is not configured in environment variables')
|
||||||
|
}
|
||||||
|
|
||||||
|
const GROK_API_URL = 'https://api.openai.com/v1'
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest): Promise<NextResponse> {
|
||||||
|
try {
|
||||||
|
const { prompt } = await req.json()
|
||||||
|
|
||||||
|
if (!prompt) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Prompt is required' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const openai = new OpenAI({
|
||||||
|
apiKey: process.env.XAI_API_KEY,
|
||||||
|
baseURL: GROK_API_URL,
|
||||||
|
});
|
||||||
|
|
||||||
|
const image = await openai.images.generate({ model: "dall-e-3", prompt: prompt });
|
||||||
|
|
||||||
|
|
||||||
|
// Extract the image URL from Grok's response
|
||||||
|
const imageUrl = image.data[0].url
|
||||||
|
|
||||||
|
if (!imageUrl) {
|
||||||
|
console.error('No image in response:', data)
|
||||||
|
throw new Error('No image generated in Grok API result')
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ imageUrl })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Grok generation error:', error)
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: error instanceof Error ? error.message : 'Failed to generate image' },
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const dynamic = 'force-dynamic'
|
@ -5,7 +5,10 @@ import WalletHeader from '../components/WalletHeader'
|
|||||||
import AIServiceCard from '../components/AIServiceCard'
|
import AIServiceCard from '../components/AIServiceCard'
|
||||||
import TextGenerationCard from '../components/TextGenerationCard'
|
import TextGenerationCard from '../components/TextGenerationCard'
|
||||||
import { generateWithFlux, FluxGenerationResult } from '../services/fluxService'
|
import { generateWithFlux, FluxGenerationResult } from '../services/fluxService'
|
||||||
|
import { generateWithAdobe, AdobeGenerationResult } from '../services/adobeService'
|
||||||
|
import { generateWithGrok, GrokGenerationResult } from '../services/grokService'
|
||||||
import { generateWithOllama, OllamaGenerationResult } from '../services/ollamaService'
|
import { generateWithOllama, OllamaGenerationResult } from '../services/ollamaService'
|
||||||
|
import { generateWithGemini, GeminiGenerationResult } from '../services/geminiService'
|
||||||
import { processMTMPayment } from '../services/paymentService'
|
import { processMTMPayment } from '../services/paymentService'
|
||||||
|
|
||||||
interface WalletState {
|
interface WalletState {
|
||||||
@ -65,6 +68,42 @@ const Page: React.FC = (): React.ReactElement => {
|
|||||||
return generateWithFlux(prompt)
|
return generateWithFlux(prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleGrokGeneration = async (prompt: string): Promise<GrokGenerationResult> => {
|
||||||
|
if (!walletState.connected || !walletState.publicKey || !window.solflare) {
|
||||||
|
return { error: 'Wallet not connected' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const paymentResult = await processMTMPayment(
|
||||||
|
walletState.publicKey,
|
||||||
|
5, // 5 MTM tokens for Grok premium service
|
||||||
|
window.solflare
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!paymentResult.success) {
|
||||||
|
return { error: paymentResult.error }
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateWithGrok(prompt)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdobeGeneration = async (prompt: string): Promise<AdobeGenerationResult> => {
|
||||||
|
if (!walletState.connected || !walletState.publicKey || !window.solflare) {
|
||||||
|
return { error: 'Wallet not connected' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const paymentResult = await processMTMPayment(
|
||||||
|
walletState.publicKey,
|
||||||
|
4, // 4 MTM tokens for Adobe premium service
|
||||||
|
window.solflare
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!paymentResult.success) {
|
||||||
|
return { error: paymentResult.error }
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateWithAdobe(prompt)
|
||||||
|
}
|
||||||
|
|
||||||
const handleOllamaGeneration = async (prompt: string): Promise<OllamaGenerationResult> => {
|
const handleOllamaGeneration = async (prompt: string): Promise<OllamaGenerationResult> => {
|
||||||
if (!walletState.connected || !walletState.publicKey || !window.solflare) {
|
if (!walletState.connected || !walletState.publicKey || !window.solflare) {
|
||||||
return { error: 'Wallet not connected' }
|
return { error: 'Wallet not connected' }
|
||||||
@ -85,16 +124,36 @@ const Page: React.FC = (): React.ReactElement => {
|
|||||||
return generateWithOllama(prompt)
|
return generateWithOllama(prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleGeminiGeneration = async (prompt: string): Promise<GeminiGenerationResult> => {
|
||||||
|
if (!walletState.connected || !walletState.publicKey || !window.solflare) {
|
||||||
|
return { error: 'Wallet not connected' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// First process payment
|
||||||
|
const paymentResult = await processMTMPayment(
|
||||||
|
walletState.publicKey,
|
||||||
|
3, // 3 MTM tokens for Gemini
|
||||||
|
window.solflare
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!paymentResult.success) {
|
||||||
|
return { error: paymentResult.error }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then generate text
|
||||||
|
return generateWithGemini(prompt)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen w-full flex flex-col items-center bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
|
<div className="min-h-screen w-full flex flex-col items-center bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900">
|
||||||
<div className="container max-w-6xl mx-auto px-4 py-8">
|
<div className="container max-w-7xl mx-auto px-4 py-8">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="text-center mb-8">
|
<div className="text-center mb-8">
|
||||||
<h1 className="text-4xl sm:text-5xl font-bold mb-4 text-transparent bg-clip-text bg-gradient-to-r from-green-400 to-emerald-600">
|
<h1 className="text-4xl sm:text-5xl font-bold mb-4 text-transparent bg-clip-text bg-gradient-to-r from-green-400 to-emerald-600">
|
||||||
AI Content Generator
|
Mark's Meme Market
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-gray-400 text-lg mb-8">
|
<p className="text-gray-400 text-lg mb-8">
|
||||||
Generate amazing content using different AI models
|
Generate memes using various AI models
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<WalletHeader
|
<WalletHeader
|
||||||
@ -105,15 +164,34 @@ const Page: React.FC = (): React.ReactElement => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* AI Services Grid */}
|
{/* AI Services Grid */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
<AIServiceCard
|
<AIServiceCard
|
||||||
title="Flux Meme Generator"
|
title="Flux Meme Generator"
|
||||||
description="Generate creative memes and images using Flux AI"
|
description="Generate images using Flux AI"
|
||||||
tokenCost={1}
|
tokenCost={1}
|
||||||
isWalletConnected={walletState.connected}
|
isWalletConnected={walletState.connected}
|
||||||
onGenerate={handleFluxGeneration}
|
onGenerate={handleFluxGeneration}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<AIServiceCard
|
||||||
|
title="X Grok Vision"
|
||||||
|
description="Advanced image generation by X's Grok AI"
|
||||||
|
tokenCost={5}
|
||||||
|
isWalletConnected={walletState.connected}
|
||||||
|
onGenerate={handleGrokGeneration}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<AIServiceCard
|
||||||
|
title="Adobe Meme Generator"
|
||||||
|
description="Generate images images using Adobe"
|
||||||
|
tokenCost={4}
|
||||||
|
isWalletConnected={walletState.connected}
|
||||||
|
onGenerate={handleAdobeGeneration}
|
||||||
|
/>*/}
|
||||||
|
|
||||||
|
|
||||||
|
{/* for another app
|
||||||
<TextGenerationCard
|
<TextGenerationCard
|
||||||
title="Ollama AI Chat"
|
title="Ollama AI Chat"
|
||||||
description="Get intelligent responses using local LLaMA2 model"
|
description="Get intelligent responses using local LLaMA2 model"
|
||||||
@ -121,12 +199,20 @@ const Page: React.FC = (): React.ReactElement => {
|
|||||||
isWalletConnected={walletState.connected}
|
isWalletConnected={walletState.connected}
|
||||||
onGenerate={handleOllamaGeneration}
|
onGenerate={handleOllamaGeneration}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<TextGenerationCard
|
||||||
|
title="Gemini Pro"
|
||||||
|
description="Advanced AI responses powered by Google's Gemini 1.5"
|
||||||
|
tokenCost={3}
|
||||||
|
isWalletConnected={walletState.connected}
|
||||||
|
onGenerate={handleGeminiGeneration}
|
||||||
|
/> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info Section */}
|
{/* Info Section */}
|
||||||
<div className="mt-12 text-center text-gray-400">
|
<div className="mt-12 text-center text-gray-400">
|
||||||
<p className="text-sm">
|
<p className="text-sm">
|
||||||
Powered by Flux AI and Ollama LLaMA2 • Requires MTM tokens for generation
|
Powered by Mark • Requires MTM tokens
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
35
src/services/adobeService.ts
Normal file
35
src/services/adobeService.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
export interface AdobeGenerationResult {
|
||||||
|
imageUrl?: string
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateWithAdobe(prompt: string): Promise<AdobeGenerationResult> {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/adobe', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ prompt }),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Failed to generate image')
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
console.log('Raw Adobe Firefly response:', data)
|
||||||
|
|
||||||
|
if (data.imageUrl) {
|
||||||
|
return { imageUrl: data.imageUrl }
|
||||||
|
} else {
|
||||||
|
console.error('Unexpected response structure:', data)
|
||||||
|
throw new Error('Invalid response format from Adobe API')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Adobe generation error:', error)
|
||||||
|
return {
|
||||||
|
error: error instanceof Error ? error.message : 'Generation failed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/services/geminiService.ts
Normal file
35
src/services/geminiService.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
export interface GeminiGenerationResult {
|
||||||
|
textResponse?: string
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateWithGemini(prompt: string): Promise<GeminiGenerationResult> {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/gemini', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ prompt }),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Failed to generate text')
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
console.log('Raw Gemini response:', data)
|
||||||
|
|
||||||
|
if (data.response) {
|
||||||
|
return { textResponse: data.response }
|
||||||
|
} else {
|
||||||
|
console.error('Unexpected response structure:', data)
|
||||||
|
throw new Error('Invalid response format from Gemini API')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Generation error:', error)
|
||||||
|
return {
|
||||||
|
error: error instanceof Error ? error.message : 'Generation failed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/services/grokService.ts
Normal file
35
src/services/grokService.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
export interface GrokGenerationResult {
|
||||||
|
imageUrl?: string
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateWithGrok(prompt: string): Promise<GrokGenerationResult> {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/grok', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ prompt }),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Failed to generate image')
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
console.log('Raw Grok response:', data)
|
||||||
|
|
||||||
|
if (data.imageUrl) {
|
||||||
|
return { imageUrl: data.imageUrl }
|
||||||
|
} else {
|
||||||
|
console.error('Unexpected response structure:', data)
|
||||||
|
throw new Error('Invalid response format from Grok API')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Grok generation error:', error)
|
||||||
|
return {
|
||||||
|
error: error instanceof Error ? error.message : 'Generation failed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { Connection, PublicKey, Transaction } from '@solana/web3.js'
|
import { Connection, PublicKey, Transaction, SystemProgram } from '@solana/web3.js'
|
||||||
import {
|
import {
|
||||||
TOKEN_PROGRAM_ID,
|
TOKEN_PROGRAM_ID,
|
||||||
createTransferInstruction,
|
createTransferInstruction,
|
||||||
@ -9,7 +9,7 @@ import {
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const MTM_TOKEN_MINT: string = '97RggLo3zV5kFGYW4yoQTxr4Xkz4Vg2WPHzNYXXWpump'
|
const MTM_TOKEN_MINT: string = '97RggLo3zV5kFGYW4yoQTxr4Xkz4Vg2WPHzNYXXWpump'
|
||||||
const PAYMENT_RECEIVER_ADDRESS: string = '9B3mGyeJTUN7ZTqyLWHLL37zL92eif239hH2pYSkvq8J'
|
const PAYMENT_RECEIVER_ADDRESS: string = 'FFDx3SdAEeXrp6BTmStB4BDHpctGsaasZq4FFcowRobY'
|
||||||
|
|
||||||
// RPC Configuration
|
// RPC Configuration
|
||||||
const SOLANA_RPC_URL: string = 'https://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4'
|
const SOLANA_RPC_URL: string = 'https://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4'
|
||||||
@ -30,6 +30,20 @@ export interface PaymentResult {
|
|||||||
error?: string
|
error?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
export async function processMTMPayment(
|
export async function processMTMPayment(
|
||||||
walletPublicKey: string,
|
walletPublicKey: string,
|
||||||
tokenAmount: number,
|
tokenAmount: number,
|
||||||
@ -40,69 +54,88 @@ export async function processMTMPayment(
|
|||||||
const mintPublicKey = new PublicKey(MTM_TOKEN_MINT)
|
const mintPublicKey = new PublicKey(MTM_TOKEN_MINT)
|
||||||
const receiverPublicKey = new PublicKey(PAYMENT_RECEIVER_ADDRESS)
|
const receiverPublicKey = new PublicKey(PAYMENT_RECEIVER_ADDRESS)
|
||||||
|
|
||||||
const senderATA = await getAssociatedTokenAddress(
|
console.log('Processing payment with keys:', {
|
||||||
mintPublicKey,
|
sender: senderPublicKey.toBase58(),
|
||||||
senderPublicKey
|
mint: mintPublicKey.toBase58(),
|
||||||
|
receiver: receiverPublicKey.toBase58(),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Find ATAs
|
||||||
|
const senderATA = await findAssociatedTokenAddress(
|
||||||
|
senderPublicKey,
|
||||||
|
mintPublicKey
|
||||||
)
|
)
|
||||||
const receiverATA = await getAssociatedTokenAddress(
|
|
||||||
mintPublicKey,
|
const receiverATA = await findAssociatedTokenAddress(
|
||||||
receiverPublicKey
|
receiverPublicKey,
|
||||||
|
mintPublicKey
|
||||||
)
|
)
|
||||||
|
|
||||||
|
console.log('Token accounts:', {
|
||||||
|
senderATA: senderATA.toBase58(),
|
||||||
|
receiverATA: receiverATA.toBase58(),
|
||||||
|
})
|
||||||
|
|
||||||
const transaction = new Transaction()
|
const transaction = new Transaction()
|
||||||
|
|
||||||
// Check and create ATAs if needed
|
// Check if accounts exist
|
||||||
const receiverATAInfo = await connection.getAccountInfo(receiverATA)
|
const [senderATAInfo, receiverATAInfo] = await Promise.all([
|
||||||
|
connection.getAccountInfo(senderATA),
|
||||||
|
connection.getAccountInfo(receiverATA),
|
||||||
|
])
|
||||||
|
|
||||||
|
// Create ATAs if they don't exist
|
||||||
if (!receiverATAInfo) {
|
if (!receiverATAInfo) {
|
||||||
|
console.log('Creating receiver token account')
|
||||||
transaction.add(
|
transaction.add(
|
||||||
createATAInstruction(
|
createAssociatedTokenAccountInstruction(
|
||||||
senderPublicKey,
|
senderPublicKey, // payer
|
||||||
receiverATA,
|
receiverATA, // ata
|
||||||
receiverPublicKey,
|
receiverPublicKey, // owner
|
||||||
mintPublicKey,
|
mintPublicKey // mint
|
||||||
TOKEN_PROGRAM_ID,
|
|
||||||
ASSOCIATED_TOKEN_PROGRAM_ID
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const senderATAInfo = await connection.getAccountInfo(senderATA)
|
|
||||||
if (!senderATAInfo) {
|
if (!senderATAInfo) {
|
||||||
|
console.log('Creating sender token account')
|
||||||
transaction.add(
|
transaction.add(
|
||||||
createATAInstruction(
|
createAssociatedTokenAccountInstruction(
|
||||||
senderPublicKey,
|
senderPublicKey, // payer
|
||||||
senderATA,
|
senderATA, // ata
|
||||||
senderPublicKey,
|
senderPublicKey, // owner
|
||||||
mintPublicKey,
|
mintPublicKey // mint
|
||||||
TOKEN_PROGRAM_ID,
|
|
||||||
ASSOCIATED_TOKEN_PROGRAM_ID
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add transfer instruction
|
// Add transfer instruction
|
||||||
const transferInstruction = createTransferInstruction(
|
transaction.add(
|
||||||
senderATA,
|
createTransferInstruction(
|
||||||
receiverATA,
|
senderATA, // from
|
||||||
senderPublicKey,
|
receiverATA, // to
|
||||||
BigInt(tokenAmount * (10 ** 6))
|
senderPublicKey, // owner
|
||||||
|
BigInt(tokenAmount * (10 ** 6)) // amount
|
||||||
|
)
|
||||||
)
|
)
|
||||||
transaction.add(transferInstruction)
|
|
||||||
|
|
||||||
const latestBlockhash = await connection.getLatestBlockhash('confirmed')
|
const latestBlockhash = await connection.getLatestBlockhash('confirmed')
|
||||||
transaction.recentBlockhash = latestBlockhash.blockhash
|
transaction.recentBlockhash = latestBlockhash.blockhash
|
||||||
transaction.feePayer = senderPublicKey
|
transaction.feePayer = senderPublicKey
|
||||||
|
|
||||||
|
console.log('Sending transaction...')
|
||||||
const { signature } = await solflareWallet.signAndSendTransaction(transaction)
|
const { signature } = await solflareWallet.signAndSendTransaction(transaction)
|
||||||
|
console.log('Transaction sent:', signature)
|
||||||
|
|
||||||
const confirmation = await connection.confirmTransaction({
|
const confirmation = await connection.confirmTransaction({
|
||||||
signature,
|
signature,
|
||||||
blockhash: latestBlockhash.blockhash,
|
blockhash: latestBlockhash.blockhash,
|
||||||
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
||||||
})
|
}, 'confirmed')
|
||||||
|
|
||||||
if (confirmation.value.err) {
|
if (confirmation.value.err) {
|
||||||
return { success: false, error: 'Payment failed to confirm' }
|
console.error('Transaction error:', confirmation.value.err)
|
||||||
|
throw new Error(`Transaction failed: ${JSON.stringify(confirmation.value.err)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
|
Loading…
Reference in New Issue
Block a user