From 9436fd5da8434d71af28f0fa6770ad0d8710dae1 Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Fri, 3 Mar 2023 10:16:26 +0000 Subject: [PATCH 01/14] chore: add sellers 184,190,191 in curation list --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a6226cb14..4cded42ee 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -130,7 +130,7 @@ jobs: ENV_NAME: "production" UPDATE_COVERAGE: false REACT_APP_ENABLE_CURATION_LISTS: true - REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183" + REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191" REACT_APP_CREATE_PROFILE_CONFIGURATION: "LENS" REACT_APP_IPFS_GATEWAY: "https://bosonprotocol.infura-ipfs.io/ipfs" REACT_APP_IPFS_IMAGE_GATEWAY: "https://gray-permanent-fly-490.mypinata.cloud/ipfs" From f3120c73132daf6bab2d0ad7cc2796a7cd09124b Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Thu, 16 Mar 2023 14:49:06 +0000 Subject: [PATCH 02/14] chore: add seller id 195 in curation list --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4cded42ee..ed5848587 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -130,7 +130,7 @@ jobs: ENV_NAME: "production" UPDATE_COVERAGE: false REACT_APP_ENABLE_CURATION_LISTS: true - REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191" + REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195" REACT_APP_CREATE_PROFILE_CONFIGURATION: "LENS" REACT_APP_IPFS_GATEWAY: "https://bosonprotocol.infura-ipfs.io/ipfs" REACT_APP_IPFS_IMAGE_GATEWAY: "https://gray-permanent-fly-490.mypinata.cloud/ipfs" From 299de6bff0d2dc3bb759a7d7635dcea6064d65a0 Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Thu, 16 Mar 2023 17:01:43 +0000 Subject: [PATCH 03/14] add seller id 196 in curation list --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ed5848587..08c964795 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -130,7 +130,7 @@ jobs: ENV_NAME: "production" UPDATE_COVERAGE: false REACT_APP_ENABLE_CURATION_LISTS: true - REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195" + REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196" REACT_APP_CREATE_PROFILE_CONFIGURATION: "LENS" REACT_APP_IPFS_GATEWAY: "https://bosonprotocol.infura-ipfs.io/ipfs" REACT_APP_IPFS_IMAGE_GATEWAY: "https://gray-permanent-fly-490.mypinata.cloud/ipfs" From 63d294cb32609e078dd056b3db0ba4c8a7867c86 Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Thu, 23 Mar 2023 16:10:11 +0000 Subject: [PATCH 04/14] chore: upgrade to react-kit 0.16.2-alpha.16 --- package-lock.json | 205 ++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 108 insertions(+), 99 deletions(-) diff --git a/package-lock.json b/package-lock.json index 181769bd3..4a3e6d888 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "@bosonprotocol/chat-sdk": "^1.3.0", - "@bosonprotocol/react-kit": "^0.16.1", + "@bosonprotocol/react-kit": "0.16.2-alpha.16", "@davatar/react": "^1.10.4", "@ethersproject/address": "^5.6.1", "@ethersproject/units": "^5.6.1", @@ -1927,11 +1927,10 @@ } }, "node_modules/@bosonprotocol/common": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@bosonprotocol/common/-/common-1.20.2.tgz", - "integrity": "sha512-iFeK4tGEH6xXhWqr2Dg3eEp2ABTb1zf2tSLUkkqAg4600uXBvnDgFCwjy715mFeYx1S/R72m5lQWlTMzxsSdzQ==", + "version": "1.21.0-alpha.11", + "resolved": "https://registry.npmjs.org/@bosonprotocol/common/-/common-1.21.0-alpha.11.tgz", "dependencies": { - "@bosonprotocol/metadata": "^1.8.1", + "@bosonprotocol/metadata": "^1.9.0-alpha.4", "@ethersproject/abi": "^5.5.0", "@ethersproject/address": "^5.5.0", "@ethersproject/bignumber": "^5.5.0", @@ -1941,11 +1940,10 @@ } }, "node_modules/@bosonprotocol/core-sdk": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@bosonprotocol/core-sdk/-/core-sdk-1.24.0.tgz", - "integrity": "sha512-QYqUH38CpwKrA7WBwO/EN3J/sKK1BUdUzncSCZoFVH4d02ViLp9ECjlOC2EMqwJ5kIAUuKNpNF38DYEYjZfP3g==", + "version": "1.25.0-alpha.11", + "resolved": "https://registry.npmjs.org/@bosonprotocol/core-sdk/-/core-sdk-1.25.0-alpha.11.tgz", "dependencies": { - "@bosonprotocol/common": "^1.20.2", + "@bosonprotocol/common": "^1.21.0-alpha.11", "@ethersproject/abi": "^5.5.0", "@ethersproject/address": "^5.5.0", "@ethersproject/bignumber": "^5.5.0", @@ -1960,43 +1958,39 @@ } }, "node_modules/@bosonprotocol/ethers-sdk": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@bosonprotocol/ethers-sdk/-/ethers-sdk-1.11.0.tgz", - "integrity": "sha512-qcPdjCu9tfVHgc/l+won0xrRWJipkJHrdw2m08l+AvQsw75xwP2BLgCOQLTejO4NaU8TPs4WzLN5o8bc7AcxHQ==", + "version": "1.11.1-alpha.16", + "resolved": "https://registry.npmjs.org/@bosonprotocol/ethers-sdk/-/ethers-sdk-1.11.1-alpha.16.tgz", "dependencies": { - "@bosonprotocol/common": "^1.20.2" + "@bosonprotocol/common": "^1.21.0-alpha.11" }, "peerDependencies": { "ethers": "^5.5.0" } }, "node_modules/@bosonprotocol/ipfs-storage": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@bosonprotocol/ipfs-storage/-/ipfs-storage-1.10.3.tgz", - "integrity": "sha512-lLy/yYqiRS+hzUGfAKtz1h9ju/tl8VNu71qiW8s8HhQuEC8m/VWypUbZjofFHygeMl/dQGyiOTuzHE0ZEQtoyw==", + "version": "1.10.4-alpha.4", + "resolved": "https://registry.npmjs.org/@bosonprotocol/ipfs-storage/-/ipfs-storage-1.10.4-alpha.4.tgz", "dependencies": { - "@bosonprotocol/metadata": "^1.8.1", + "@bosonprotocol/metadata": "^1.9.0-alpha.4", "ipfs-http-client": "^56.0.1", "multiformats": "^9.6.4", "uint8arrays": "^3.0.0" } }, "node_modules/@bosonprotocol/metadata": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@bosonprotocol/metadata/-/metadata-1.8.1.tgz", - "integrity": "sha512-+LuyzMn8ojSU1D+soxA4avcRA4jIRi1pXBNwI7iP3qfmITJuBvq5nB6TZVnSUNGioGn7v6XRFklKh+wNJMp3PA==", + "version": "1.9.0-alpha.4", + "resolved": "https://registry.npmjs.org/@bosonprotocol/metadata/-/metadata-1.9.0-alpha.4.tgz", "dependencies": { "schema-to-yup": "^1.11.11" } }, "node_modules/@bosonprotocol/react-kit": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@bosonprotocol/react-kit/-/react-kit-0.16.1.tgz", - "integrity": "sha512-xNUiHcV/vJdXmgCKMpy1linCbfIYf5AGDMnLjjn/2aGEVly2GipTgeSfm+4kP4ot1RRQ7n/hF07e0GzZMhFeUg==", + "version": "0.16.2-alpha.16", + "resolved": "https://registry.npmjs.org/@bosonprotocol/react-kit/-/react-kit-0.16.2-alpha.16.tgz", "dependencies": { - "@bosonprotocol/core-sdk": "^1.24.0", - "@bosonprotocol/ethers-sdk": "^1.11.0", - "@bosonprotocol/ipfs-storage": "^1.10.3", + "@bosonprotocol/core-sdk": "^1.25.0-alpha.11", + "@bosonprotocol/ethers-sdk": "^1.11.1-alpha.16", + "@bosonprotocol/ipfs-storage": "^1.10.4-alpha.4", "@ethersproject/units": "^5.6.0", "@tippyjs/react": "^4.2.6", "@web3-react/core": "8.0.18-beta.0", @@ -9049,9 +9043,9 @@ } }, "node_modules/cborg": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/cborg/-/cborg-1.9.6.tgz", - "integrity": "sha512-XmiD+NWTk9xg31d8MdXgW46bSZd95ELllxjbjdWGyHAtpTw+cf8iG3NibWgTWRnfWfxtcihVa5Pm0gchHiO3JQ==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/cborg/-/cborg-1.10.1.tgz", + "integrity": "sha512-et6Qm8MOUY2kCWa5GKk2MlBVoPjHv0hQBmlzI/Z7+5V3VJCeIkGehIB3vWknNsm2kOkAIs6wEKJFJo8luWQQ/w==", "bin": { "cborg": "cli.js" } @@ -14567,34 +14561,49 @@ } }, "node_modules/ipfs-utils": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-9.0.9.tgz", - "integrity": "sha512-auKjNok5bFhid1JmnXn+QFKaGrKrxgbUpVD0v4XkIKIH7kCR9zWOihErPKBDfJXfF8YycQ+SvPgX1XOpDgUC5Q==", + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-9.0.14.tgz", + "integrity": "sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==", "dependencies": { "any-signal": "^3.0.0", + "browser-readablestream-to-it": "^1.0.0", "buffer": "^6.0.1", "electron-fetch": "^1.7.2", "err-code": "^3.0.1", "is-electron": "^2.2.0", "iso-url": "^1.1.5", + "it-all": "^1.0.4", "it-glob": "^1.0.1", "it-to-stream": "^1.0.0", "merge-options": "^3.0.4", "nanoid": "^3.1.20", "native-fetch": "^3.0.0", - "node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", - "react-native-fetch-api": "^2.0.0", + "node-fetch": "^2.6.8", + "react-native-fetch-api": "^3.0.0", "stream-to-it": "^0.2.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, "node_modules/ipfs-utils/node_modules/node-fetch": { - "name": "@achingbrain/node-fetch", - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g==", - "license": "MIT", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/is-absolute": { @@ -14730,9 +14739,9 @@ } }, "node_modules/is-electron": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz", - "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" }, "node_modules/is-extendable": { "version": "0.1.1", @@ -22739,9 +22748,9 @@ } }, "node_modules/parse-duration": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.2.tgz", - "integrity": "sha512-Dg27N6mfok+ow1a2rj/nRjtCfaKrHUZV2SJpEn/s8GaVUSlf4GGRCRP1c13Hj+wfPKVMrFDqLMLITkYKgKxyyg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.3.tgz", + "integrity": "sha512-o6NAh12na5VvR6nFejkU0gpQ8jmOY9Y9sTU2ke3L3G/d/3z8jqmbBbeyBGHU73P4JLXfc7tJARygIK3WGIkloA==" }, "node_modules/parse-filepath": { "version": "1.0.2", @@ -24808,9 +24817,9 @@ } }, "node_modules/react-native-fetch-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-native-fetch-api/-/react-native-fetch-api-2.0.0.tgz", - "integrity": "sha512-GOA8tc1EVYLnHvma/TU9VTgLOyralO7eATRuCDchQveXW9Fr9vXygyq9iwqmM7YRZ8qRJfEt9xOS7OYMdJvRFw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-native-fetch-api/-/react-native-fetch-api-3.0.0.tgz", + "integrity": "sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==", "dependencies": { "p-defer": "^3.0.0" } @@ -25834,9 +25843,9 @@ } }, "node_modules/schema-to-yup": { - "version": "1.12.8", - "resolved": "https://registry.npmjs.org/schema-to-yup/-/schema-to-yup-1.12.8.tgz", - "integrity": "sha512-5yqbBckLRu0kT46T1lf81Sr3kD18SwhYNDv9ftTWcEyDssdCAbuIHDsozg0gpfOmpydnqZKCtPTRKUBiiKiSTg==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/schema-to-yup/-/schema-to-yup-1.12.9.tgz", + "integrity": "sha512-cCax3dTLXjEVI0KLWpmiqYHUPuY+6pOVIgrZeRH1A7M34ph53SxiqIwLLARPSdr8praKFC3SS9VM+mcK8UlxMw==", "dependencies": { "dashify": "^2.0.0", "uniq": "^1.0.1", @@ -30188,11 +30197,10 @@ } }, "@bosonprotocol/common": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@bosonprotocol/common/-/common-1.20.2.tgz", - "integrity": "sha512-iFeK4tGEH6xXhWqr2Dg3eEp2ABTb1zf2tSLUkkqAg4600uXBvnDgFCwjy715mFeYx1S/R72m5lQWlTMzxsSdzQ==", + "version": "1.21.0-alpha.11", + "resolved": "https://registry.npmjs.org/@bosonprotocol/common/-/common-1.21.0-alpha.11.tgz", "requires": { - "@bosonprotocol/metadata": "^1.8.1", + "@bosonprotocol/metadata": "^1.9.0-alpha.4", "@ethersproject/abi": "^5.5.0", "@ethersproject/address": "^5.5.0", "@ethersproject/bignumber": "^5.5.0", @@ -30202,11 +30210,10 @@ } }, "@bosonprotocol/core-sdk": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@bosonprotocol/core-sdk/-/core-sdk-1.24.0.tgz", - "integrity": "sha512-QYqUH38CpwKrA7WBwO/EN3J/sKK1BUdUzncSCZoFVH4d02ViLp9ECjlOC2EMqwJ5kIAUuKNpNF38DYEYjZfP3g==", + "version": "1.25.0-alpha.11", + "resolved": "https://registry.npmjs.org/@bosonprotocol/core-sdk/-/core-sdk-1.25.0-alpha.11.tgz", "requires": { - "@bosonprotocol/common": "^1.20.2", + "@bosonprotocol/common": "^1.21.0-alpha.11", "@ethersproject/abi": "^5.5.0", "@ethersproject/address": "^5.5.0", "@ethersproject/bignumber": "^5.5.0", @@ -30221,40 +30228,36 @@ } }, "@bosonprotocol/ethers-sdk": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@bosonprotocol/ethers-sdk/-/ethers-sdk-1.11.0.tgz", - "integrity": "sha512-qcPdjCu9tfVHgc/l+won0xrRWJipkJHrdw2m08l+AvQsw75xwP2BLgCOQLTejO4NaU8TPs4WzLN5o8bc7AcxHQ==", + "version": "1.11.1-alpha.16", + "resolved": "https://registry.npmjs.org/@bosonprotocol/ethers-sdk/-/ethers-sdk-1.11.1-alpha.16.tgz", "requires": { - "@bosonprotocol/common": "^1.20.2" + "@bosonprotocol/common": "^1.21.0-alpha.11" } }, "@bosonprotocol/ipfs-storage": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@bosonprotocol/ipfs-storage/-/ipfs-storage-1.10.3.tgz", - "integrity": "sha512-lLy/yYqiRS+hzUGfAKtz1h9ju/tl8VNu71qiW8s8HhQuEC8m/VWypUbZjofFHygeMl/dQGyiOTuzHE0ZEQtoyw==", + "version": "1.10.4-alpha.4", + "resolved": "https://registry.npmjs.org/@bosonprotocol/ipfs-storage/-/ipfs-storage-1.10.4-alpha.4.tgz", "requires": { - "@bosonprotocol/metadata": "^1.8.1", + "@bosonprotocol/metadata": "^1.9.0-alpha.4", "ipfs-http-client": "^56.0.1", "multiformats": "^9.6.4", "uint8arrays": "^3.0.0" } }, "@bosonprotocol/metadata": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@bosonprotocol/metadata/-/metadata-1.8.1.tgz", - "integrity": "sha512-+LuyzMn8ojSU1D+soxA4avcRA4jIRi1pXBNwI7iP3qfmITJuBvq5nB6TZVnSUNGioGn7v6XRFklKh+wNJMp3PA==", + "version": "1.9.0-alpha.4", + "resolved": "https://registry.npmjs.org/@bosonprotocol/metadata/-/metadata-1.9.0-alpha.4.tgz", "requires": { "schema-to-yup": "^1.11.11" } }, "@bosonprotocol/react-kit": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@bosonprotocol/react-kit/-/react-kit-0.16.1.tgz", - "integrity": "sha512-xNUiHcV/vJdXmgCKMpy1linCbfIYf5AGDMnLjjn/2aGEVly2GipTgeSfm+4kP4ot1RRQ7n/hF07e0GzZMhFeUg==", + "version": "0.16.2-alpha.16", + "resolved": "https://registry.npmjs.org/@bosonprotocol/react-kit/-/react-kit-0.16.2-alpha.16.tgz", "requires": { - "@bosonprotocol/core-sdk": "^1.24.0", - "@bosonprotocol/ethers-sdk": "^1.11.0", - "@bosonprotocol/ipfs-storage": "^1.10.3", + "@bosonprotocol/core-sdk": "^1.25.0-alpha.11", + "@bosonprotocol/ethers-sdk": "^1.11.1-alpha.16", + "@bosonprotocol/ipfs-storage": "^1.10.4-alpha.4", "@ethersproject/units": "^5.6.0", "@tippyjs/react": "^4.2.6", "@web3-react/core": "8.0.18-beta.0", @@ -34907,9 +34910,9 @@ "version": "2.4.0" }, "cborg": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/cborg/-/cborg-1.9.6.tgz", - "integrity": "sha512-XmiD+NWTk9xg31d8MdXgW46bSZd95ELllxjbjdWGyHAtpTw+cf8iG3NibWgTWRnfWfxtcihVa5Pm0gchHiO3JQ==" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/cborg/-/cborg-1.10.1.tgz", + "integrity": "sha512-et6Qm8MOUY2kCWa5GKk2MlBVoPjHv0hQBmlzI/Z7+5V3VJCeIkGehIB3vWknNsm2kOkAIs6wEKJFJo8luWQQ/w==" }, "ccount": { "version": "2.0.1" @@ -38472,29 +38475,35 @@ } }, "ipfs-utils": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-9.0.9.tgz", - "integrity": "sha512-auKjNok5bFhid1JmnXn+QFKaGrKrxgbUpVD0v4XkIKIH7kCR9zWOihErPKBDfJXfF8YycQ+SvPgX1XOpDgUC5Q==", + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-9.0.14.tgz", + "integrity": "sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==", "requires": { "any-signal": "^3.0.0", + "browser-readablestream-to-it": "^1.0.0", "buffer": "^6.0.1", "electron-fetch": "^1.7.2", "err-code": "^3.0.1", "is-electron": "^2.2.0", "iso-url": "^1.1.5", + "it-all": "^1.0.4", "it-glob": "^1.0.1", "it-to-stream": "^1.0.0", "merge-options": "^3.0.4", "nanoid": "^3.1.20", "native-fetch": "^3.0.0", - "node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", - "react-native-fetch-api": "^2.0.0", + "node-fetch": "^2.6.8", + "react-native-fetch-api": "^3.0.0", "stream-to-it": "^0.2.2" }, "dependencies": { "node-fetch": { - "version": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g==" + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "requires": { + "whatwg-url": "^5.0.0" + } } } }, @@ -38559,9 +38568,9 @@ "version": "2.2.1" }, "is-electron": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz", - "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" }, "is-extendable": { "version": "0.1.1", @@ -43601,9 +43610,9 @@ } }, "parse-duration": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.2.tgz", - "integrity": "sha512-Dg27N6mfok+ow1a2rj/nRjtCfaKrHUZV2SJpEn/s8GaVUSlf4GGRCRP1c13Hj+wfPKVMrFDqLMLITkYKgKxyyg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.3.tgz", + "integrity": "sha512-o6NAh12na5VvR6nFejkU0gpQ8jmOY9Y9sTU2ke3L3G/d/3z8jqmbBbeyBGHU73P4JLXfc7tJARygIK3WGIkloA==" }, "parse-filepath": { "version": "1.0.2", @@ -44720,9 +44729,9 @@ } }, "react-native-fetch-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-native-fetch-api/-/react-native-fetch-api-2.0.0.tgz", - "integrity": "sha512-GOA8tc1EVYLnHvma/TU9VTgLOyralO7eATRuCDchQveXW9Fr9vXygyq9iwqmM7YRZ8qRJfEt9xOS7OYMdJvRFw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-native-fetch-api/-/react-native-fetch-api-3.0.0.tgz", + "integrity": "sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==", "requires": { "p-defer": "^3.0.0" } @@ -45348,9 +45357,9 @@ } }, "schema-to-yup": { - "version": "1.12.8", - "resolved": "https://registry.npmjs.org/schema-to-yup/-/schema-to-yup-1.12.8.tgz", - "integrity": "sha512-5yqbBckLRu0kT46T1lf81Sr3kD18SwhYNDv9ftTWcEyDssdCAbuIHDsozg0gpfOmpydnqZKCtPTRKUBiiKiSTg==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/schema-to-yup/-/schema-to-yup-1.12.9.tgz", + "integrity": "sha512-cCax3dTLXjEVI0KLWpmiqYHUPuY+6pOVIgrZeRH1A7M34ph53SxiqIwLLARPSdr8praKFC3SS9VM+mcK8UlxMw==", "requires": { "dashify": "^2.0.0", "uniq": "^1.0.1", diff --git a/package.json b/package.json index 64f92ac7d..50537d3c6 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ }, "dependencies": { "@bosonprotocol/chat-sdk": "^1.3.0", - "@bosonprotocol/react-kit": "^0.16.1", + "@bosonprotocol/react-kit": "0.16.2-alpha.16", "@davatar/react": "^1.10.4", "@ethersproject/address": "^5.6.1", "@ethersproject/units": "^5.6.1", From d9e0bccd0ac9bc4dd852b35a2b050ce0232f64fd Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Mon, 27 Mar 2023 22:16:57 +0100 Subject: [PATCH 05/14] chore: add seller 202 in curation list (#574) --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 08c964795..accc6cc4d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -130,7 +130,7 @@ jobs: ENV_NAME: "production" UPDATE_COVERAGE: false REACT_APP_ENABLE_CURATION_LISTS: true - REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196" + REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196,202" REACT_APP_CREATE_PROFILE_CONFIGURATION: "LENS" REACT_APP_IPFS_GATEWAY: "https://bosonprotocol.infura-ipfs.io/ipfs" REACT_APP_IPFS_IMAGE_GATEWAY: "https://gray-permanent-fly-490.mypinata.cloud/ipfs" From 8e36500e7d30c774d4a3b21c7122d9a419ef0f6e Mon Sep 17 00:00:00 2001 From: albertfolch-redeemeum <102516373+albertfolch-redeemeum@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:08:45 +0200 Subject: [PATCH 06/14] chore: add seller 197 in seller curation list (#576) --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index accc6cc4d..67f41b8a2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -130,7 +130,7 @@ jobs: ENV_NAME: "production" UPDATE_COVERAGE: false REACT_APP_ENABLE_CURATION_LISTS: true - REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196,202" + REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196,197,202" REACT_APP_CREATE_PROFILE_CONFIGURATION: "LENS" REACT_APP_IPFS_GATEWAY: "https://bosonprotocol.infura-ipfs.io/ipfs" REACT_APP_IPFS_IMAGE_GATEWAY: "https://gray-permanent-fly-490.mypinata.cloud/ipfs" From aa719fca7c77b23456aa5abacdf2939c593f3663 Mon Sep 17 00:00:00 2001 From: albertfolch-redeemeum <102516373+albertfolch-redeemeum@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:06:24 +0200 Subject: [PATCH 07/14] fix: custom fonts (#579) * fix: custom font * refactor: remove wrong import --- src/lib/styles/GlobalStyle.tsx | 3 ++- src/lib/types/externals.d.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/styles/GlobalStyle.tsx b/src/lib/styles/GlobalStyle.tsx index 36752c3fc..643f7bb09 100644 --- a/src/lib/styles/GlobalStyle.tsx +++ b/src/lib/styles/GlobalStyle.tsx @@ -1,5 +1,6 @@ import { createGlobalStyle } from "styled-components"; +import barlowRegular from "../../assets/fonts/Barlow-Regular.ttf"; import { breakpoint } from "../../lib/styles/breakpoint"; import { colors } from "../../lib/styles/colors"; @@ -19,7 +20,7 @@ const GlobalStyle = createGlobalStyle<{ }>` @font-face { font-family: barlow; - src: url(src/assets/fonts/Barlow-Regular.ttf); + src: url(${barlowRegular}); font-weight: normal; } * { diff --git a/src/lib/types/externals.d.ts b/src/lib/types/externals.d.ts index 7c5b8894e..ec5f4ff93 100644 --- a/src/lib/types/externals.d.ts +++ b/src/lib/types/externals.d.ts @@ -1,3 +1,5 @@ declare module "@metamask/jazzicon"; declare module "pretty"; + +declare module "*.ttf"; From eeec6b844627e06ab607722e4be0eb26a43d961e Mon Sep 17 00:00:00 2001 From: albertfolch-redeemeum <102516373+albertfolch-redeemeum@users.noreply.github.com> Date: Tue, 11 Apr 2023 11:15:06 +0200 Subject: [PATCH 08/14] feat: add neuropolitical custom font (#587) --- src/assets/fonts/neuropolitical_rg.ttf | Bin 0 -> 83832 bytes src/lib/styles/GlobalStyle.tsx | 6 ++++++ src/pages/custom-store/store-fields.ts | 4 ++++ 3 files changed, 10 insertions(+) create mode 100644 src/assets/fonts/neuropolitical_rg.ttf diff --git a/src/assets/fonts/neuropolitical_rg.ttf b/src/assets/fonts/neuropolitical_rg.ttf new file mode 100644 index 0000000000000000000000000000000000000000..26bbb63ceaf2719cfff5b8e6bc78ef98e281551b GIT binary patch literal 83832 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 Ytq1w3ThQq0eNj*C^M?G{ghjRdAJbRmLI3~& literal 0 HcmV?d00001 diff --git a/src/lib/styles/GlobalStyle.tsx b/src/lib/styles/GlobalStyle.tsx index 643f7bb09..b009e74ea 100644 --- a/src/lib/styles/GlobalStyle.tsx +++ b/src/lib/styles/GlobalStyle.tsx @@ -1,6 +1,7 @@ import { createGlobalStyle } from "styled-components"; import barlowRegular from "../../assets/fonts/Barlow-Regular.ttf"; +import neuropolitical_rg from "../../assets/fonts/neuropolitical_rg.ttf"; import { breakpoint } from "../../lib/styles/breakpoint"; import { colors } from "../../lib/styles/colors"; @@ -23,6 +24,11 @@ const GlobalStyle = createGlobalStyle<{ src: url(${barlowRegular}); font-weight: normal; } + @font-face { + font-family: neuropolitical_rg; + src: url(${neuropolitical_rg}); + font-weight: normal; + } * { box-sizing: border-box; } diff --git a/src/pages/custom-store/store-fields.ts b/src/pages/custom-store/store-fields.ts index dd9a16a37..51066127c 100644 --- a/src/pages/custom-store/store-fields.ts +++ b/src/pages/custom-store/store-fields.ts @@ -190,6 +190,10 @@ export const formModel = { { label: "Barlow", value: "barlow" // defined in src/lib/styles/GlobalStyle.tsx + }, + { + label: "Neuropolitical", + value: "neuropolitical_rg" // defined in src/lib/styles/GlobalStyle.tsx } ] }, From 518bfda34239489f79e9c9ad07543f6cb4c6bd50 Mon Sep 17 00:00:00 2001 From: albertfolch-redeemeum <102516373+albertfolch-redeemeum@users.noreply.github.com> Date: Wed, 12 Apr 2023 16:27:35 +0200 Subject: [PATCH 09/14] chore: add seller 207 in seller curation list (#591) --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 67f41b8a2..228322209 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -130,7 +130,7 @@ jobs: ENV_NAME: "production" UPDATE_COVERAGE: false REACT_APP_ENABLE_CURATION_LISTS: true - REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196,197,202" + REACT_APP_SELLER_CURATION_LIST: "2,4,5,6,7,8,9,11,12,13,14,16,27,129,171,172,180,181,182,183,184,190,191,195,196,197,202,207" REACT_APP_CREATE_PROFILE_CONFIGURATION: "LENS" REACT_APP_IPFS_GATEWAY: "https://bosonprotocol.infura-ipfs.io/ipfs" REACT_APP_IPFS_IMAGE_GATEWAY: "https://gray-permanent-fly-490.mypinata.cloud/ipfs" From a0b328e43c1835e5f64b75d20e41ff1b36057e8a Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Fri, 21 Apr 2023 15:10:11 +0100 Subject: [PATCH 10/14] fix: tabnapping protection (#594) --- src/components/detail/DetailWidget/TokenGated.tsx | 4 +++- .../disputeResolver/ManageDisputes/DisputesTable.tsx | 3 ++- src/components/footer/Footer.tsx | 8 +++++--- src/components/toasts/SuccessTransactionToast.tsx | 3 ++- src/pages/profile/seller/SellerSocial.tsx | 10 ++++++++-- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/components/detail/DetailWidget/TokenGated.tsx b/src/components/detail/DetailWidget/TokenGated.tsx index 4356f18a1..7743b2740 100644 --- a/src/components/detail/DetailWidget/TokenGated.tsx +++ b/src/components/detail/DetailWidget/TokenGated.tsx @@ -7,6 +7,7 @@ import { CONFIG } from "../../../lib/config"; import { colors } from "../../../lib/styles/colors"; import { Offer } from "../../../lib/types/offer"; import { IPrice } from "../../../lib/utils/convertPrice"; +import { sanitizeUrl } from "../../../lib/utils/url"; import { useCoreSDK } from "../../../lib/utils/useCoreSdk"; import { useConvertedPrice } from "../../price/useConvertedPrice"; import Grid from "../../ui/Grid"; @@ -176,8 +177,9 @@ const TokenGated = ({ {openseaLinkToOriginalMainnetCollection} diff --git a/src/components/disputeResolver/ManageDisputes/DisputesTable.tsx b/src/components/disputeResolver/ManageDisputes/DisputesTable.tsx index 47e65ca5c..2cb50805e 100644 --- a/src/components/disputeResolver/ManageDisputes/DisputesTable.tsx +++ b/src/components/disputeResolver/ManageDisputes/DisputesTable.tsx @@ -14,6 +14,7 @@ import copyToClipboard from "../../../lib/utils/copyToClipboard"; import { getDateTimestamp } from "../../../lib/utils/getDateTimestamp"; import { Disputes } from "../../../lib/utils/hooks/useExchanges"; import { useKeepQueryParamsNavigate } from "../../../lib/utils/hooks/useKeepQueryParamsNavigate"; +import { sanitizeUrl } from "../../../lib/utils/url"; import { useModal } from "../../modal/useModal"; import Price from "../../price"; import PaginationPages from "../../seller/common/PaginationPages"; @@ -175,7 +176,7 @@ export default function DisputesTable({ disputes }: Props) { whiteSpace: "pre" }} onClick={() => { - copyToClipboard(emailAddress).then(() => { + copyToClipboard(sanitizeUrl(emailAddress)).then(() => { toast(() => "Seller e-mail has been copied to clipboard"); }); }} diff --git a/src/components/footer/Footer.tsx b/src/components/footer/Footer.tsx index 11d07d825..5bd17af97 100644 --- a/src/components/footer/Footer.tsx +++ b/src/components/footer/Footer.tsx @@ -5,6 +5,7 @@ import logo from "../../../src/assets/logo-white.svg"; import { BosonRoutes } from "../../lib/routing/routes"; import { breakpoint } from "../../lib/styles/breakpoint"; import { useBreakpoints } from "../../lib/utils/hooks/useBreakpoints"; +import { sanitizeUrl } from "../../lib/utils/url"; import SocialLogo, { SocialLogoValues } from "../../pages/custom-store/SocialLogo"; @@ -112,9 +113,9 @@ function Socials() { return socialMediaLinks.map(({ url, value }) => { return ( @@ -241,9 +242,10 @@ export default function FooterComponent() { return ( {footerLink.label} diff --git a/src/components/toasts/SuccessTransactionToast.tsx b/src/components/toasts/SuccessTransactionToast.tsx index dd202f73a..981b372bb 100644 --- a/src/components/toasts/SuccessTransactionToast.tsx +++ b/src/components/toasts/SuccessTransactionToast.tsx @@ -1,6 +1,7 @@ import { Toast } from "react-hot-toast"; import { colors } from "../../lib/styles/colors"; +import { sanitizeUrl } from "../../lib/utils/url"; import Grid from "../ui/Grid"; import Typography from "../ui/Typography"; import SuccessToast from "./common/SuccessToast"; @@ -33,7 +34,7 @@ export default function SuccessTransactionToast({ View details ) : url ? ( - + View details ) : null} diff --git a/src/pages/profile/seller/SellerSocial.tsx b/src/pages/profile/seller/SellerSocial.tsx index eab5eb813..706e45e02 100644 --- a/src/pages/profile/seller/SellerSocial.tsx +++ b/src/pages/profile/seller/SellerSocial.tsx @@ -7,6 +7,7 @@ import { Profile, ProfileFieldsFragment } from "../../../lib/utils/hooks/lens/graphql/generated"; +import { sanitizeUrl } from "../../../lib/utils/url"; import { preAppendHttps } from "../../../lib/validation/regex/url"; import { DetailShareWrapper, @@ -26,7 +27,12 @@ function RenderSocial({ icon: Icon }: RenderSocialProps) { return ( - + {Icon ? Icon : } ); @@ -60,7 +66,7 @@ export default function SellerSocial({ {/* TODO: Removed as we don't have discord in lens profile */} {/* */} {lensUrl !== false && ( - } href={lensUrl} /> + } href={sanitizeUrl(lensUrl)} /> )} From 352414b4e4b022867ae51bf3258d7fa8be252b61 Mon Sep 17 00:00:00 2001 From: albertfolch-redeemeum <102516373+albertfolch-redeemeum@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:50:24 +0200 Subject: [PATCH 11/14] feat: change seller deposit copy (#603) --- src/components/product/TermsOfExchange.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/product/TermsOfExchange.tsx b/src/components/product/TermsOfExchange.tsx index 492e67bee..d455b2f31 100644 --- a/src/components/product/TermsOfExchange.tsx +++ b/src/components/product/TermsOfExchange.tsx @@ -224,7 +224,7 @@ export default function TermsOfExchange() {
From 73e2b69774a6cf58da15973e0481e3dd618b1c6f Mon Sep 17 00:00:00 2001 From: albertfolch-redeemeum <102516373+albertfolch-redeemeum@users.noreply.github.com> Date: Tue, 25 Apr 2023 12:32:27 +0200 Subject: [PATCH 12/14] feat: remove promotional banner (#601) (#604) * feat: remove promotional banner * fix: build --- src/components/banner/Banner.tsx | 49 -------------------------------- src/components/header/Header.tsx | 44 ---------------------------- 2 files changed, 93 deletions(-) delete mode 100644 src/components/banner/Banner.tsx diff --git a/src/components/banner/Banner.tsx b/src/components/banner/Banner.tsx deleted file mode 100644 index da2b2fed9..000000000 --- a/src/components/banner/Banner.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { ArrowRight } from "phosphor-react"; -import styled from "styled-components"; - -import Grid from "../../components/ui/Grid"; -import { colors } from "../../lib/styles/colors"; -import Typography from "../ui/Typography"; - -const BannerContainer = styled.a` - display: block; - text-align: center; - background-color: ${colors.secondary}; - color: ${colors.white}; - transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1); - padding-left: 0.5rem; - padding-right: 0.5rem; - &:hover { - background-color: ${colors.black}; - [data-arrow-right] { - transform: translate(1rem, 0); - } - } -`; -const ArrowWrapper = styled(Grid)` - background-color: ${colors.primary}; - padding: 0.315rem; - color: ${colors.black}; - width: auto; - transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1); -`; - -function Banner() { - return ( - - - - Get 50% of the purchase price of any item as a $BOSON reward - - - - - - - ); -} - -export default Banner; diff --git a/src/components/header/Header.tsx b/src/components/header/Header.tsx index d9e7a7594..3f6405838 100644 --- a/src/components/header/Header.tsx +++ b/src/components/header/Header.tsx @@ -11,7 +11,6 @@ import { colors } from "../../lib/styles/colors"; import { zIndex } from "../../lib/styles/zIndex"; import { useBreakpoints } from "../../lib/utils/hooks/useBreakpoints"; import { useCustomStoreQueryParameter } from "../../pages/custom-store/useCustomStoreQueryParameter"; -import Banner from "../banner/Banner"; import { LinkWithQuery } from "../customNavigation/LinkWithQuery"; import Layout from "../Layout"; import ViewTxButton from "../transactions/ViewTxButton"; @@ -23,40 +22,6 @@ const smallWidth = "180px"; const mediumWidth = "225px"; const sideMargin = "1rem"; const closedHeaderWidth = "75px"; -const SideBannerContainer = styled.div<{ - $navigationBarPosition: string; - $isSideBarOpen: boolean; -}>` - ${({ $navigationBarPosition, $isSideBarOpen }) => { - if ("left" === $navigationBarPosition) { - return css` - ${$isSideBarOpen - ? css` - margin-left: ${smallWidth}; - ${breakpoint.m} { - margin-left: ${mediumWidth}; - } - ` - : css` - margin-left: ${closedHeaderWidth}; - `} - `; - } else if ("right" === $navigationBarPosition) { - return css` - ${$isSideBarOpen - ? css` - margin-right: ${smallWidth}; - ${breakpoint.m} { - margin-right: ${mediumWidth}; - } - ` - : css` - margin-right: ${closedHeaderWidth}; - `} - `; - } - }} -`; const Header = styled.header<{ $navigationBarPosition: string; @@ -312,20 +277,11 @@ const HeaderComponent = forwardRef( return ( <> - {withBanner && isSideNavBar && ( - - - - )}
- {withBanner && !isSideNavBar && } Date: Thu, 27 Apr 2023 11:30:45 +0200 Subject: [PATCH 13/14] feat: relist offer (#596) (#606) * feat: relist offer (#596) * feat: relist offer * refactor: remove comments * fix: uuids * fix: disable relist button if you are not the operator --- src/components/datepicker/Calendar.tsx | 6 +- src/components/datepicker/DatePicker.tsx | 17 +- .../detail/DetailWidget/DetailWidget.tsx | 2 +- src/components/form/Datepicker.tsx | 4 +- src/components/modal/Modal.tsx | 2 + src/components/modal/ModalComponents.tsx | 14 +- .../components/Chat/CancelExchangeModal.tsx | 2 +- .../components/Chat/ResolveDisputeModal.tsx | 2 +- .../modal/components/CompleteExchange.tsx | 4 +- .../modal/components/ExpireVoucherModal.tsx | 2 +- .../ExportExchangesWithDeliveryModal.tsx | 21 +- .../modal/components/ProductCreateSuccess.tsx | 56 ++- .../RedeemModal/Confirmation/Confirmation.tsx | 2 +- .../RelistOfferModal/RelistOfferModal.tsx | 251 ++++++++++++ .../modal/components/RetractDisputeModal.tsx | 2 +- .../modal/components/RevokeProduct.tsx | 2 +- .../SellerFinance/FinanceDeposit.tsx | 2 +- .../SellerFinance/FinanceWithdraw.tsx | 2 +- .../TransactionFailedModal.tsx} | 14 +- .../modal/components/VoidProduct.tsx | 2 +- src/components/product/Preview.tsx | 24 +- .../{ => coreTermsOfSale}/CoreTermsOfSale.tsx | 38 +- .../coreTermsOfSale/CoreTermsOfSaleDates.tsx | 35 ++ src/components/product/utils/const.ts | 13 +- src/components/product/utils/initialValues.ts | 3 - .../product/utils/validationSchema.ts | 48 +-- src/components/seller/SellerWrapper.tsx | 2 + .../seller/exchanges/SellerExchanges.tsx | 8 +- .../seller/products/SellerProductsTable.tsx | 140 ++++--- src/lib/types/yup.d.ts | 24 ++ src/lib/utils/hooks/offer/useCreateOffers.tsx | 332 ++++++++++++++++ src/lib/utils/hooks/useDidMountEffect.ts | 14 + src/lib/validation/index.ts | 17 +- src/lib/validation/isItBeforeNow.ts | 3 + .../validation/isOfferValidityDatesValid.ts | 3 + src/lib/validation/isRedemptionDatesValid.ts | 5 +- src/pages/chat/ChatProvider/ChatContext.ts | 2 + src/pages/chat/ChatProvider/ChatProvider.tsx | 8 +- src/pages/create-product/CreateProduct.tsx | 21 +- .../create-product/CreateProductInner.tsx | 376 ++---------------- .../create-product/utils/buildCondition.ts | 18 +- .../create-product/utils/dataValidator.ts | 18 +- src/pages/create-product/utils/index.tsx | 2 +- src/pages/dispute-centre/DisputeCentre.tsx | 2 +- 44 files changed, 994 insertions(+), 571 deletions(-) create mode 100644 src/components/modal/components/RelistOfferModal/RelistOfferModal.tsx rename src/components/modal/components/Transactions/{ConfirmationFailedModal/ConfirmationFailedModal.tsx => TransactionFailedModal/TransactionFailedModal.tsx} (76%) rename src/components/product/{ => coreTermsOfSale}/CoreTermsOfSale.tsx (85%) create mode 100644 src/components/product/coreTermsOfSale/CoreTermsOfSaleDates.tsx create mode 100644 src/lib/types/yup.d.ts create mode 100644 src/lib/utils/hooks/offer/useCreateOffers.tsx create mode 100644 src/lib/utils/hooks/useDidMountEffect.ts diff --git a/src/components/datepicker/Calendar.tsx b/src/components/datepicker/Calendar.tsx index b1910e4e2..78d2461a9 100644 --- a/src/components/datepicker/Calendar.tsx +++ b/src/components/datepicker/Calendar.tsx @@ -69,9 +69,13 @@ export default function Calendar({ {rows.map(({ text, value, current }: ICalendarCell, i: number) => { - const disabled: boolean = period + const isBeforeMinDate = minDate ? value?.isBefore(minDate, "day") : false; + const isAfterMaxDate = maxDate + ? value?.isAfter(maxDate, "day") + : false; + const disabled: boolean = isBeforeMinDate || isAfterMaxDate; return ( | null; - onChange?: (selected: Dayjs | Array) => void; + onChange?: (selected: Dayjs | Array | null) => void; error?: string; period: boolean; selectTime: boolean; @@ -37,8 +38,10 @@ const handleInitialDates = ( let endDate: Dayjs | null = null; if (Array.isArray(initialValue)) { - startDate = dayjs(initialValue[0]); - endDate = dayjs(initialValue[1]); + if (initialValue.length) { + startDate = dayjs(initialValue[0]); + endDate = dayjs(initialValue[1]); + } } else { startDate = dayjs(initialValue); } @@ -109,7 +112,7 @@ export default function DatePicker({ } }; - useEffect(() => { + useDidMountEffect(() => { if ( (!period && date !== null) || (period && date !== null && secondDate !== null) @@ -122,7 +125,13 @@ export default function DatePicker({ (period && date === null && secondDate === null) ) { setShownDate("Choose dates..."); + if (period) { + onChange?.([]); + } else { + onChange?.(null); + } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [date, secondDate, period]); useEffect(() => { diff --git a/src/components/detail/DetailWidget/DetailWidget.tsx b/src/components/detail/DetailWidget/DetailWidget.tsx index 33b19f3ed..3e4086fae 100644 --- a/src/components/detail/DetailWidget/DetailWidget.tsx +++ b/src/components/detail/DetailWidget/DetailWidget.tsx @@ -669,7 +669,7 @@ const DetailWidget: React.FC = ({ "code" in error && (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } else { showModal(modalTypes.DETAIL_WIDGET, { title: "An error occurred", diff --git a/src/components/form/Datepicker.tsx b/src/components/form/Datepicker.tsx index 51dd06df7..ce5e0f8fe 100644 --- a/src/components/form/Datepicker.tsx +++ b/src/components/form/Datepicker.tsx @@ -5,7 +5,7 @@ import DatePicker from "../datepicker/DatePicker"; import Error from "./Error"; import type { DatepickerProps } from "./types"; -export default function DatepickerComponent({ +export default function Datepicker({ name, period = false, selectTime = false, @@ -17,7 +17,7 @@ export default function DatepickerComponent({ const displayError = typeof errorMessage === typeof "string" && errorMessage !== ""; - const handleChange = (date: Dayjs | Array) => { + const handleChange = (date: Dayjs | Array | null) => { if (!meta.touched) { helpers.setTouched(true); } diff --git a/src/components/modal/Modal.tsx b/src/components/modal/Modal.tsx index 37b7c1edc..1aad1a9f4 100644 --- a/src/components/modal/Modal.tsx +++ b/src/components/modal/Modal.tsx @@ -239,6 +239,8 @@ const Content = styled.div<{ `}; ${({ $modalType }) => { switch ($modalType) { + case "RELIST_OFFER": + case "EXPORT_EXCHANGES_WITH_DELIVERY": case "REDEEM": return css` overflow: visible; diff --git a/src/components/modal/ModalComponents.tsx b/src/components/modal/ModalComponents.tsx index 9e2f8ac2f..263b26b2a 100644 --- a/src/components/modal/ModalComponents.tsx +++ b/src/components/modal/ModalComponents.tsx @@ -20,12 +20,13 @@ import ProductCreateSuccess from "./components/ProductCreateSuccess"; import ProgressBarModal from "./components/ProgressBarModal"; import RedeemModal from "./components/RedeemModal/RedeemModal"; import RedeemSuccessModal from "./components/RedeemModal/RedeemSuccessModal"; +import { RelistOfferModal } from "./components/RelistOfferModal/RelistOfferModal"; import RetractDisputeModal from "./components/RetractDisputeModal"; import RevokeProduct from "./components/RevokeProduct"; import FinanceDeposit from "./components/SellerFinance/FinanceDeposit"; import FinanceWithdraw from "./components/SellerFinance/FinanceWithdraw"; -import ConfirmationFailedModal from "./components/Transactions/ConfirmationFailedModal/ConfirmationFailedModal"; import RecentTransactionsModal from "./components/Transactions/RecentTransactionsModal/RecentTransactionsModal"; +import TransactionFailedModal from "./components/Transactions/TransactionFailedModal/TransactionFailedModal"; import TransactionSubmittedModal from "./components/Transactions/TransactionSubmittedModal/TransactionSubmittedModal"; import WaitingForConfirmationModal from "./components/Transactions/WaitingForConfirmationModal/WaitingForConfirmationModal"; import Upload from "./components/Upload"; @@ -35,7 +36,7 @@ import WhatIsRedeem from "./components/WhatIsRedeem"; export const MODAL_TYPES = { CANCEL_EXCHANGE: "CANCEL_EXCHANGE", COMPLETE_EXCHANGE: "COMPLETE_EXCHANGE", - CONFIRMATION_FAILED: "CONFIRMATION_FAILED", + TRANSACTION_FAILED: "TRANSACTION_FAILED", CREATE_PRODUCT_DRAFT: "CREATE_PRODUCT_DRAFT", CREATE_PROFILE: "CREATE_PROFILE", CUSTOM_STORE: "CUSTOM_STORE", @@ -64,13 +65,14 @@ export const MODAL_TYPES = { WAITING_FOR_CONFIRMATION: "WAITING_FOR_CONFIRMATION", WHAT_IS_REDEEM: "WHAT_IS_REDEEM", PROGRESS_BAR: "PROGRESS_BAR", - EXPORT_EXCHANGES_WITH_DELIVERY: "EXPORT_EXCHANGES_WITH_DELIVERY" + EXPORT_EXCHANGES_WITH_DELIVERY: "EXPORT_EXCHANGES_WITH_DELIVERY", + RELIST_OFFER: "RELIST_OFFER" } as const; export const MODAL_COMPONENTS = { [MODAL_TYPES.CANCEL_EXCHANGE]: CancelExchangeModal, [MODAL_TYPES.COMPLETE_EXCHANGE]: CompleteExchange, - [MODAL_TYPES.CONFIRMATION_FAILED]: ConfirmationFailedModal, + [MODAL_TYPES.TRANSACTION_FAILED]: TransactionFailedModal, [MODAL_TYPES.CREATE_PRODUCT_DRAFT]: CreateProductDraft, [MODAL_TYPES.CREATE_PROFILE]: CreateProfileModal, [MODAL_TYPES.CUSTOM_STORE]: CustomStore, @@ -99,5 +101,7 @@ export const MODAL_COMPONENTS = { [MODAL_TYPES.WAITING_FOR_CONFIRMATION]: WaitingForConfirmationModal, [MODAL_TYPES.WHAT_IS_REDEEM]: WhatIsRedeem, [MODAL_TYPES.PROGRESS_BAR]: ProgressBarModal, - [MODAL_TYPES.EXPORT_EXCHANGES_WITH_DELIVERY]: ExportExchangesWithDeliveryModal + [MODAL_TYPES.EXPORT_EXCHANGES_WITH_DELIVERY]: + ExportExchangesWithDeliveryModal, + [MODAL_TYPES.RELIST_OFFER]: RelistOfferModal } as const; diff --git a/src/components/modal/components/Chat/CancelExchangeModal.tsx b/src/components/modal/components/Chat/CancelExchangeModal.tsx index 4988b09eb..495f627c4 100644 --- a/src/components/modal/components/Chat/CancelExchangeModal.tsx +++ b/src/components/modal/components/Chat/CancelExchangeModal.tsx @@ -205,7 +205,7 @@ export default function CancelExchangeModal({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } else { showModal(modalTypes.DETAIL_WIDGET, { title: "An error occurred", diff --git a/src/components/modal/components/Chat/ResolveDisputeModal.tsx b/src/components/modal/components/Chat/ResolveDisputeModal.tsx index e7c137d63..58cf9d768 100644 --- a/src/components/modal/components/Chat/ResolveDisputeModal.tsx +++ b/src/components/modal/components/Chat/ResolveDisputeModal.tsx @@ -176,7 +176,7 @@ export default function ResolveDisputeModal({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } setResolveDisputeError(error as Error); } diff --git a/src/components/modal/components/CompleteExchange.tsx b/src/components/modal/components/CompleteExchange.tsx index 971845f49..9dfd79d1c 100644 --- a/src/components/modal/components/CompleteExchange.tsx +++ b/src/components/modal/components/CompleteExchange.tsx @@ -229,7 +229,7 @@ export default function CompleteExchange({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }} onPendingSignature={() => { @@ -278,7 +278,7 @@ export default function CompleteExchange({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }} onPendingSignature={() => { diff --git a/src/components/modal/components/ExpireVoucherModal.tsx b/src/components/modal/components/ExpireVoucherModal.tsx index 79867f540..2a8a05caa 100644 --- a/src/components/modal/components/ExpireVoucherModal.tsx +++ b/src/components/modal/components/ExpireVoucherModal.tsx @@ -189,7 +189,7 @@ export default function ExpireVoucherModal({ exchange }: Props) { (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }} onPendingSignature={() => { diff --git a/src/components/modal/components/ExportExchangesWithDeliveryModal.tsx b/src/components/modal/components/ExportExchangesWithDeliveryModal.tsx index b99eaa507..def6ad5e5 100644 --- a/src/components/modal/components/ExportExchangesWithDeliveryModal.tsx +++ b/src/components/modal/components/ExportExchangesWithDeliveryModal.tsx @@ -1,5 +1,5 @@ import dayjs, { Dayjs } from "dayjs"; -import { useState } from "react"; +import { useMemo, useState } from "react"; import DatePicker from "../../datepicker/DatePicker"; import BosonButton from "../../ui/BosonButton"; @@ -11,14 +11,11 @@ export default function ExportExchangesWithDeliveryModal({ }: { onExport: (from?: Dayjs) => void; }) { - const [from, setFrom] = useState(dayjs()); + const today = useMemo(() => dayjs(), []); + const [from, setFrom] = useState(today); + const initialDate = useMemo(() => dayjs().startOf("month"), []); return ( - + Option 1

@@ -34,8 +31,8 @@ export default function ExportExchangesWithDeliveryModal({ period={false} selectTime minDate={null} - maxDate={dayjs()} - initialValue={dayjs()} + maxDate={today} + initialValue={initialDate} onChange={(date) => { setFrom(date as Dayjs); }} @@ -57,9 +54,7 @@ export default function ExportExchangesWithDeliveryModal({ delivery information.This option will always include, if it exists in the chat conversation, the delivery information.

- onExport()}> - Export - + onExport()}>Export
); diff --git a/src/components/modal/components/ProductCreateSuccess.tsx b/src/components/modal/components/ProductCreateSuccess.tsx index 280f693f9..f44378132 100644 --- a/src/components/modal/components/ProductCreateSuccess.tsx +++ b/src/components/modal/components/ProductCreateSuccess.tsx @@ -15,8 +15,7 @@ import { Break, ModalGrid, ModalImageWrapper, - Widget, - WidgetButtonWrapper + Widget } from "../../detail/Detail.style"; import DetailTable from "../../detail/DetailTable"; import TokenGated from "../../detail/DetailWidget/TokenGated"; @@ -31,7 +30,7 @@ interface Props { name: string; image: string; offer: any; - onCreateNewProject: () => void; + onCreateNew?: () => void; onViewMyItem: () => void; hasMultipleVariants: boolean; } @@ -82,11 +81,6 @@ const StyledIndicator = styled(ProgressPrimitive.Indicator)` height: 100%; transition: transform 660ms cubic-bezier(0.65, 0, 0.35, 1); `; -const StyledWidgetButtonWrapper = styled(WidgetButtonWrapper)` - button { - width: 50%; - } -`; const FundTile = styled(Typography)` font-weight: 600; @@ -114,7 +108,7 @@ export default function ProductCreateSuccess({ name, image, offer, - onCreateNewProject, + onCreateNew, onViewMyItem, hasMultipleVariants }: Props) { @@ -133,10 +127,6 @@ export default function ProductCreateSuccess({ [convertedPrice, offer] ); - const handleCreateNew = () => { - onCreateNewProject(); - }; - const suggestedAmount = FixedNumber.fromString( formatUnits( BigNumber.from(offer?.sellerDeposit).mul(Number(offer?.quantityInitial)), @@ -199,14 +189,16 @@ export default function ProductCreateSuccess({ />
- + {offer.condition && ( + + )}
@@ -254,7 +246,7 @@ export default function ProductCreateSuccess({ )} - + View my item - - Create new - - - + {onCreateNew && ( + + Create new + + + )} +
diff --git a/src/components/modal/components/RedeemModal/Confirmation/Confirmation.tsx b/src/components/modal/components/RedeemModal/Confirmation/Confirmation.tsx index 96551f2d9..5a7e14f35 100644 --- a/src/components/modal/components/RedeemModal/Confirmation/Confirmation.tsx +++ b/src/components/modal/components/RedeemModal/Confirmation/Confirmation.tsx @@ -218,7 +218,7 @@ ${FormModel.formFields.phone.placeholder}: ${phoneField.value}`; (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }} onPendingSignature={async () => { diff --git a/src/components/modal/components/RelistOfferModal/RelistOfferModal.tsx b/src/components/modal/components/RelistOfferModal/RelistOfferModal.tsx new file mode 100644 index 000000000..3a25e167b --- /dev/null +++ b/src/components/modal/components/RelistOfferModal/RelistOfferModal.tsx @@ -0,0 +1,251 @@ +import { EvaluationMethod } from "@bosonprotocol/common"; +import { offers, productV1, subgraph } from "@bosonprotocol/react-kit"; +import * as Sentry from "@sentry/browser"; +import { Form, Formik } from "formik"; +import React from "react"; +import toast from "react-hot-toast"; +import { generatePath } from "react-router-dom"; +import uuid from "react-uuid"; + +import { UrlParameters } from "../../../../lib/routing/parameters"; +import { ProductRoutes } from "../../../../lib/routing/routes"; +import { useCreateOffers } from "../../../../lib/utils/hooks/offer/useCreateOffers"; +import { useKeepQueryParamsNavigate } from "../../../../lib/utils/hooks/useKeepQueryParamsNavigate"; +import { useCoreSDK } from "../../../../lib/utils/useCoreSdk"; +import Yup from "../../../../lib/validation/index"; +import { ExtendedOffer } from "../../../../pages/explore/WithAllOffers"; +import { CoreTermsOfSaleDates } from "../../../product/coreTermsOfSale/CoreTermsOfSaleDates"; +import { + commonCoreTermsOfSaleValidationSchema, + TOKEN_CRITERIA +} from "../../../product/utils"; +import SuccessTransactionToast from "../../../toasts/SuccessTransactionToast"; +import BosonButton from "../../../ui/BosonButton"; +import Typography from "../../../ui/Typography"; +import { useModal } from "../../useModal"; + +interface RelistOfferModalProps { + offer: ExtendedOffer; + onRelistedSuccessfully?: () => void; +} + +const validationSchema = Yup.object({ + offerValidityPeriod: + commonCoreTermsOfSaleValidationSchema["offerValidityPeriod"], + + redemptionPeriod: commonCoreTermsOfSaleValidationSchema["redemptionPeriod"] +}); + +type RelistType = Yup.InferType; + +export const RelistOfferModal: React.FC = ({ + offer, + onRelistedSuccessfully +}) => { + const coreSDK = useCoreSDK(); + const { showModal, hideModal } = useModal(); + const navigate = useKeepQueryParamsNavigate(); + const { mutateAsync: createOffers } = useCreateOffers(); + return ( + + initialValues={{ + offerValidityPeriod: [], + redemptionPeriod: [] + }} + validationSchema={validationSchema} + onSubmit={async (values) => { + try { + const validFromDate = values.offerValidityPeriod[0] + .toDate() + .getTime(); + const validUntilDate = values.offerValidityPeriod[1] + .toDate() + .getTime(); + const voucherRedeemableFromDate = values.redemptionPeriod[0] + .toDate() + .getTime(); + const voucherRedeemableUntilDate = values.redemptionPeriod[1] + .toDate() + .getTime(); + const isMultiVariant = (offer.additional?.variants?.length ?? []) > 1; + const { condition } = offer; + const isTokenGated = !!condition; + const offersToCreate: offers.CreateOfferArgs[] = []; + const productUuid = uuid(); + for (const variant of offer.additional?.variants ?? []) { + const metadataUuid = uuid(); + const originalMetadata = (await coreSDK.getMetadata( + variant.metadataHash + )) as productV1.ProductV1Metadata; + const redeemableAtValue = originalMetadata.attributes.find( + (attribute) => attribute.trait_type === "Redeemable At" + )?.value; + const origin = redeemableAtValue; + const metadataAsString = JSON.stringify(originalMetadata); + const metadata = JSON.parse( + metadataAsString + .replaceAll( + `${origin}/#/license/${originalMetadata.uuid}`, + `${origin}/#/license/${metadataUuid}` + ) + .replaceAll( + `${origin}/#/variant-uuid/${originalMetadata.uuid}`, + `${origin}/#/variant-uuid/${metadataUuid}` + ) + .replaceAll( + `${origin}/#/offer-uuid/${originalMetadata.uuid}`, + `${origin}/#/offer-uuid/${metadataUuid}` + ) + ) as productV1.ProductV1Metadata; + const metadataHash = await coreSDK.storeMetadata({ + ...metadata, + uuid: metadataUuid, + attributes: [ + ...metadata.attributes.filter( + (attribute) => + attribute.trait_type !== "Redeemable Until" && + attribute.display_type !== "date" + ), + { + trait_type: "Redeemable Until", + value: voucherRedeemableUntilDate.toString(), + display_type: "date" + } + ], + exchangePolicy: { + ...metadata.exchangePolicy, + uuid: Date.now().toString() + }, + product: { + ...metadata.product, + uuid: productUuid + } + }); + const offerData = { + price: variant.price.toString(), + sellerDeposit: variant.sellerDeposit.toString(), + buyerCancelPenalty: variant.buyerCancelPenalty.toString(), + quantityAvailable: variant.quantityAvailable.toString(), + voucherRedeemableFromDateInMS: + voucherRedeemableFromDate.toString(), + voucherRedeemableUntilDateInMS: voucherRedeemableUntilDate, + voucherValidDurationInMS: variant.voucherValidDuration.toString(), + validFromDateInMS: validFromDate.toString(), + validUntilDateInMS: validUntilDate.toString(), + disputePeriodDurationInMS: ( + Number(variant.disputePeriodDuration) * 1000 + ).toString(), + resolutionPeriodDurationInMS: + variant.resolutionPeriodDuration.toString(), + exchangeToken: variant.exchangeToken?.address, + disputeResolverId: variant.disputeResolverId, + agentId: variant.agentId, // no agent + metadataUri: `ipfs://${metadataHash}`, + metadataHash: metadataHash + }; + offersToCreate.push(offerData); + } + const handleOpenSuccessModal = ( + offerInfo: subgraph.OfferFieldsFragment + ) => { + if (!offerInfo.metadata) { + return; + } + const onViewMyItem = () => { + hideModal(); + const id = productUuid; + const pathname = generatePath(ProductRoutes.ProductDetail, { + [UrlParameters.uuid]: id + }); + navigate({ pathname }); + }; + showModal( + "PRODUCT_CREATE_SUCCESS", + { + title: `Offer ${offerInfo.id}`, + name: offerInfo.metadata.name, + message: "You have successfully relisted:", + image: offerInfo.metadata.image, + price: offerInfo.price, + offer: offerInfo, + hasMultipleVariants: isMultiVariant, + onViewMyItem + }, + "auto" + ); + }; + + await createOffers({ + isMultiVariant, + offersToCreate, + tokenGatedInfo: isTokenGated + ? { + maxCommits: condition.maxCommits, + minBalance: condition.threshold, + tokenContract: condition.tokenAddress, + tokenCriteria: + condition.method === EvaluationMethod.SpecificToken + ? TOKEN_CRITERIA[1] + : TOKEN_CRITERIA[0], + tokenId: condition.tokenId, + tokenType: condition.tokenType + } + : null, + conditionDecimals: Number(offer.exchangeToken.decimals), + onCreatedOffersWithVariants: ({ firstOffer }) => { + toast((t) => ( + { + handleOpenSuccessModal( + firstOffer || ({} as subgraph.OfferFieldsFragment) + ); + }} + /> + )); + }, + onCreatedSingleOffers: ({ offer: createdOffer }) => { + toast((t) => ( + { + handleOpenSuccessModal( + createdOffer || ({} as subgraph.OfferFieldsFragment) + ); + }} + /> + )); + } + }); + onRelistedSuccessfully?.(); + } catch (error) { + showModal("TRANSACTION_FAILED", { + errorMessage: "Something went wrong", + detailedErrorMessage: + "Please try again or try disconnecting and reconnecting your wallet before relisting the offer" + }); + console.error(error); + Sentry.captureException(error); + } + }} + > + {({ isValid }) => { + return ( +
+ + Relisting an offer duplicates all its contents except for the IDs, + Offer Validity period, and Redemption period as they may be in the + past, so you will need to define them here. + + + + Relist Offer + + + ); + }} + + ); +}; diff --git a/src/components/modal/components/RetractDisputeModal.tsx b/src/components/modal/components/RetractDisputeModal.tsx index 9890127af..064f389d4 100644 --- a/src/components/modal/components/RetractDisputeModal.tsx +++ b/src/components/modal/components/RetractDisputeModal.tsx @@ -126,7 +126,7 @@ export default function RetractDisputeModal({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } setRetractDisputeError(error as Error); } diff --git a/src/components/modal/components/RevokeProduct.tsx b/src/components/modal/components/RevokeProduct.tsx index 5ff62749e..4855972b9 100644 --- a/src/components/modal/components/RevokeProduct.tsx +++ b/src/components/modal/components/RevokeProduct.tsx @@ -141,7 +141,7 @@ export default function RevokeProduct({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }} onPendingSignature={() => { diff --git a/src/components/modal/components/SellerFinance/FinanceDeposit.tsx b/src/components/modal/components/SellerFinance/FinanceDeposit.tsx index 57cc5c31a..4e00486ba 100644 --- a/src/components/modal/components/SellerFinance/FinanceDeposit.tsx +++ b/src/components/modal/components/SellerFinance/FinanceDeposit.tsx @@ -186,7 +186,7 @@ export default function FinanceDeposit({ "code" in error && (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } setDepositError(error); reload(); diff --git a/src/components/modal/components/SellerFinance/FinanceWithdraw.tsx b/src/components/modal/components/SellerFinance/FinanceWithdraw.tsx index f4295b6cc..e3e938349 100644 --- a/src/components/modal/components/SellerFinance/FinanceWithdraw.tsx +++ b/src/components/modal/components/SellerFinance/FinanceWithdraw.tsx @@ -194,7 +194,7 @@ export default function FinanceWithdraw({ "code" in error && (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } setWithdrawError(error); reload(); diff --git a/src/components/modal/components/Transactions/ConfirmationFailedModal/ConfirmationFailedModal.tsx b/src/components/modal/components/Transactions/TransactionFailedModal/TransactionFailedModal.tsx similarity index 76% rename from src/components/modal/components/Transactions/ConfirmationFailedModal/ConfirmationFailedModal.tsx rename to src/components/modal/components/Transactions/TransactionFailedModal/TransactionFailedModal.tsx index a80a4b490..eaea6a455 100644 --- a/src/components/modal/components/Transactions/ConfirmationFailedModal/ConfirmationFailedModal.tsx +++ b/src/components/modal/components/Transactions/TransactionFailedModal/TransactionFailedModal.tsx @@ -6,10 +6,16 @@ import Grid from "../../../../ui/Grid"; import Typography from "../../../../ui/Typography"; import { useModal } from "../../../useModal"; -export default function ConfirmationFailedModal() { +export default function TransactionFailedModal({ + errorMessage, + detailedErrorMessage +}: { + errorMessage: string; + detailedErrorMessage?: string; +}) { const { updateProps, store } = useModal(); useEffect(() => { - updateProps<"CONFIRMATION_FAILED">({ + updateProps<"TRANSACTION_FAILED">({ ...store, modalProps: { ...store.modalProps @@ -26,7 +32,7 @@ export default function ConfirmationFailedModal() { - Confirmation Failed + {errorMessage || "Confirmation Failed"} - Please retry this action + {detailedErrorMessage || "Please retry this action"} ); diff --git a/src/components/modal/components/VoidProduct.tsx b/src/components/modal/components/VoidProduct.tsx index ada873b9e..3b70b09d2 100644 --- a/src/components/modal/components/VoidProduct.tsx +++ b/src/components/modal/components/VoidProduct.tsx @@ -340,7 +340,7 @@ export default function VoidProduct({ (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }} onPendingSignature={() => { diff --git a/src/components/product/Preview.tsx b/src/components/product/Preview.tsx index efa98afe5..67097b73f 100644 --- a/src/components/product/Preview.tsx +++ b/src/components/product/Preview.tsx @@ -126,18 +126,18 @@ export default function Preview({ const commonTermsOfSale = isMultiVariant ? values.variantsCoreTermsOfSale : values.coreTermsOfSale; - const validFromDateInMS = Date.parse( - commonTermsOfSale.offerValidityPeriod[0] - ); - const validUntilDateInMS = Date.parse( - commonTermsOfSale.offerValidityPeriod[1] - ); - const voucherRedeemableFromDateInMS = Date.parse( - commonTermsOfSale.redemptionPeriod[0] - ); - const voucherRedeemableUntilDateInMS = Date.parse( - commonTermsOfSale.redemptionPeriod[1] - ); + const validFromDateInMS = commonTermsOfSale.offerValidityPeriod[0] + .toDate() + .getTime(); + const validUntilDateInMS = commonTermsOfSale.offerValidityPeriod[1] + .toDate() + .getTime(); + const voucherRedeemableFromDateInMS = commonTermsOfSale.redemptionPeriod[0] + .toDate() + .getTime(); + const voucherRedeemableUntilDateInMS = commonTermsOfSale.redemptionPeriod[1] + .toDate() + .getTime(); const quantityAvailable = isMultiVariant ? firstVariant.quantity : values.coreTermsOfSale.quantity; diff --git a/src/components/product/CoreTermsOfSale.tsx b/src/components/product/coreTermsOfSale/CoreTermsOfSale.tsx similarity index 85% rename from src/components/product/CoreTermsOfSale.tsx rename to src/components/product/coreTermsOfSale/CoreTermsOfSale.tsx index d15d91ecb..1cb684b0c 100644 --- a/src/components/product/CoreTermsOfSale.tsx +++ b/src/components/product/coreTermsOfSale/CoreTermsOfSale.tsx @@ -1,21 +1,22 @@ import { useState } from "react"; import styled from "styled-components"; -import { useCoreSDK } from "../../lib/utils/useCoreSdk"; -import { Datepicker, FormField, Input, Select, Textarea } from "../form"; -import BosonButton from "../ui/BosonButton"; +import { useCoreSDK } from "../../../lib/utils/useCoreSdk"; +import { FormField, Input, Select, Textarea } from "../../form"; +import BosonButton from "../../ui/BosonButton"; import { ContainerProductPage, ProductButtonGroup, SectionTitle -} from "./Product.styles"; +} from "../Product.styles"; import { OPTIONS_CURRENCIES, OPTIONS_TOKEN_GATED, TOKEN_CRITERIA, TOKEN_TYPES -} from "./utils"; -import { useCreateForm } from "./utils/useCreateForm"; +} from "../utils"; +import { useCreateForm } from "../utils/useCreateForm"; +import { CoreTermsOfSaleDates } from "./CoreTermsOfSaleDates"; const PriceContainer = styled.div` display: grid; @@ -97,16 +98,6 @@ export default function CoreTermsOfSale({ isMultiVariant }: Props) { {values[prefix].tokenGatedOffer.value === "true" && ( <> - {/* TODO: enable once we have more than one variant */} - {/* - - )} - - - - - - + = ({ + prefix +}) => { + const fixedPrefix = prefix ? `${prefix}.` : ""; + return ( + <> + + + + + + + + ); +}; diff --git a/src/components/product/utils/const.ts b/src/components/product/utils/const.ts index fecd7e2d2..ed435e99a 100644 --- a/src/components/product/utils/const.ts +++ b/src/components/product/utils/const.ts @@ -79,14 +79,7 @@ export const OPTIONS_TOKEN_GATED = [ value: "true", label: "Yes" } -]; - -export const TOKEN_GATED_VARIANTS = [ - { - value: "all", - label: "All" - } -]; +] as const; export const TOKEN_TYPES = [ { @@ -101,7 +94,7 @@ export const TOKEN_TYPES = [ value: "erc1155", label: "ERC1155" } -]; +] as const; export const TOKEN_CRITERIA = [ { @@ -112,7 +105,7 @@ export const TOKEN_CRITERIA = [ value: "tokenid", label: "tokenId" } -]; +] as const; export const OPTIONS_EXCHANGE_POLICY = [ { diff --git a/src/components/product/utils/initialValues.ts b/src/components/product/utils/initialValues.ts index 7322b0c97..0656f1f07 100644 --- a/src/components/product/utils/initialValues.ts +++ b/src/components/product/utils/initialValues.ts @@ -11,7 +11,6 @@ import { OPTIONS_UNIT, OPTIONS_WEIGHT, TOKEN_CRITERIA, - TOKEN_GATED_VARIANTS, TOKEN_TYPES } from "./const"; import { CreateProductForm } from "./types"; @@ -89,7 +88,6 @@ export const coreTermsOfSaleInitialValues = { currency: OPTIONS_CURRENCIES[0], quantity: 1, tokenGatedOffer: OPTIONS_TOKEN_GATED[0], - tokenGatedVariants: TOKEN_GATED_VARIANTS[0], tokenContract: "", tokenType: TOKEN_TYPES[0], minBalance: undefined, @@ -105,7 +103,6 @@ export const coreTermsOfSaleInitialValues = { export const variantsCoreTermsOfSaleInitialValues = { variantsCoreTermsOfSale: { tokenGatedOffer: OPTIONS_TOKEN_GATED[0], - tokenGatedVariants: TOKEN_GATED_VARIANTS[0], tokenContract: "", tokenType: TOKEN_TYPES[0], minBalance: undefined, diff --git a/src/components/product/utils/validationSchema.ts b/src/components/product/utils/validationSchema.ts index a75ccb2cb..76e22db7a 100644 --- a/src/components/product/utils/validationSchema.ts +++ b/src/components/product/utils/validationSchema.ts @@ -175,30 +175,23 @@ export const productInformationValidationSchema = Yup.object({ }) }); -const commonCoreTermsOfSaleValidationSchema = { +export const commonCoreTermsOfSaleValidationSchema = { tokenGatedOffer: Yup.object() .shape({ value: Yup.string(), label: Yup.string() }) .default([{ value: "", label: "" }]), - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - offerValidityPeriod: Yup.mixed().isItBeforeNow().isOfferValidityDatesValid(), // prettier-ignore - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - redemptionPeriod: Yup.mixed().isItBeforeNow().isRedemptionDatesValid(), // prettier-ignore - tokenGatedVariants: Yup.object() - .when(["tokenGatedOffer"], { - is: (tokenGated: SelectDataProps) => - tokenGated?.value === OPTIONS_TOKEN_GATED[1].value, - then: (schema) => schema.required(validationMessage.required) - }) - .shape({ - value: Yup.string(), - label: Yup.string() - }) - .default([{ value: "", label: "" }]), + offerValidityPeriod: Yup.array() + .required(validationMessage.required) + .min(2, validationMessage.required) + .isItBeforeNow() + .isOfferValidityDatesValid(), + redemptionPeriod: Yup.array() + .required(validationMessage.required) + .min(2, validationMessage.required) + .isItBeforeNow() + .isRedemptionDatesValid(), tokenContract: Yup.string() .when(["tokenGatedOffer"], { is: (tokenGated: SelectDataProps) => @@ -226,17 +219,14 @@ const commonCoreTermsOfSaleValidationSchema = { label: Yup.string() }) .default([{ value: "", label: "" }]), - tokenCriteria: Yup.object() - .when(["tokenGatedOffer"], { - is: (tokenGated: SelectDataProps) => - tokenGated?.value === OPTIONS_TOKEN_GATED[1].value, - then: (schema) => schema.required(validationMessage.required) - }) - .shape({ - value: Yup.string(), - label: Yup.string() - }) - .default([{ value: "", label: "" }]), + tokenCriteria: Yup.object({ + value: Yup.string(), + label: Yup.string() + }).when(["tokenGatedOffer"], { + is: (tokenGated: SelectDataProps) => + tokenGated?.value === OPTIONS_TOKEN_GATED[1].value, + then: (schema) => schema.required(validationMessage.required) + }), minBalance: Yup.string().when( ["tokenGatedOffer", "tokenType", "tokenCriteria"], { diff --git a/src/components/seller/SellerWrapper.tsx b/src/components/seller/SellerWrapper.tsx index f9aa6c00c..d353048b6 100644 --- a/src/components/seller/SellerWrapper.tsx +++ b/src/components/seller/SellerWrapper.tsx @@ -7,6 +7,7 @@ const SellerMain = styled.main` padding: 1.375rem 2.5rem 2.75rem 2.5rem; background: ${colors.lightGrey}; min-height: calc(100vh - 5.5rem); + overflow: hidden; `; const SellerTitle = styled(Typography)` margin: 0 0 1.25rem 0; @@ -16,6 +17,7 @@ const SellerInner = styled.div` padding: 1rem; box-shadow: 0px 0px 5px 0px rgb(0 0 0 / 2%), 0px 0px 10px 0px rgb(0 0 0 / 2%), 0px 0px 15px 0px rgb(0 0 0 / 5%); + overflow: auto; `; export const LoadingWrapper = styled.div` text-align: center; diff --git a/src/components/seller/exchanges/SellerExchanges.tsx b/src/components/seller/exchanges/SellerExchanges.tsx index a8dd0bbda..6d6d67b3b 100644 --- a/src/components/seller/exchanges/SellerExchanges.tsx +++ b/src/components/seller/exchanges/SellerExchanges.tsx @@ -180,7 +180,7 @@ export default function SellerExchanges({ const [csvData, setCsvData] = useState([] as CSVData[]); const [loading, setLoading] = useState(false); - const { initialize, bosonXmtp, isInitializing } = useChatContext(); + const { initialize, bosonXmtp, isInitializing, error } = useChatContext(); const worker = useWorker(createWorker); const location = useLocation(); @@ -568,6 +568,12 @@ export default function SellerExchanges({ } ); + useEffect(() => { + if ((bosonXmtp && loading) || error) { + setLoading(false); + } + }, [bosonXmtp, loading, error]); + useEffect(() => { if (bosonXmtp && loading && csvData.length === 0) { showExchangesExportModal(); diff --git a/src/components/seller/products/SellerProductsTable.tsx b/src/components/seller/products/SellerProductsTable.tsx index 60164d3e0..42505665a 100644 --- a/src/components/seller/products/SellerProductsTable.tsx +++ b/src/components/seller/products/SellerProductsTable.tsx @@ -244,6 +244,11 @@ const Span = styled.span` margin-right: 1rem; } `; +const RelistButton = styled(Button)` + * { + line-height: 21px; + } +`; const statusOrder = [ OffersKit.OfferState.NOT_YET_VALID, @@ -623,7 +628,7 @@ export default function SellerProductsTable({ /> ), quantity: ( - + {offer?.quantityAvailable}/{offer?.quantityInitial} ), @@ -644,56 +649,89 @@ export default function SellerProductsTable({ ), - action: !( - status === OffersKit.OfferState.EXPIRED || - status === OffersKit.OfferState.VOIDED || - offer?.quantityAvailable === "0" - ) && ( - { - if (offer) { - if (showVariant) { - showModal( - modalTypes.VOID_PRODUCT, - { - title: "Void Confirmation", - offers: offer.additional?.variants.filter( - (variant) => { - variant.validUntilDate; - return ( - !variant.voided && - !dayjs( - getDateTimestamp(offer?.validUntilDate) - ).isBefore(dayjs()) - ); - } - ) as Offer[], - refetch - }, - "s" - ); - } else { - showModal( - modalTypes.VOID_PRODUCT, - { - title: "Void Confirmation", - offerId: offer.id, - offer, - refetch - }, - "xs" - ); - } - } - }} - > - Void - - ) + action: (() => { + const withVoidButton = !( + status === OffersKit.OfferState.EXPIRED || + status === OffersKit.OfferState.VOIDED || + offer?.quantityAvailable === "0" + ); + return ( + + {withVoidButton && ( + { + if (offer) { + if (showVariant) { + showModal( + modalTypes.VOID_PRODUCT, + { + title: "Void Confirmation", + offers: offer.additional?.variants.filter( + (variant) => { + variant.validUntilDate; + return ( + !variant.voided && + !dayjs( + getDateTimestamp(offer?.validUntilDate) + ).isBefore(dayjs()) + ); + } + ) as Offer[], + refetch + }, + "s" + ); + } else { + showModal( + modalTypes.VOID_PRODUCT, + { + title: "Void Confirmation", + offerId: offer.id, + offer, + refetch + }, + "xs" + ); + } + } + }} + > + Void + + )} + [0]["onClick"]> + >[0] + ) => { + event.stopPropagation(); + if (!offer) { + return; + } + showModal(modalTypes.RELIST_OFFER, { + title: `Relist Offer "${offer.metadata.name}"`, + offer, + onRelistedSuccessfully: refetch + }); + }} + > + Relist + + + ); + })() }; }) .sort(compareOffersSortByStatus), diff --git a/src/lib/types/yup.d.ts b/src/lib/types/yup.d.ts new file mode 100644 index 000000000..eab5992ff --- /dev/null +++ b/src/lib/types/yup.d.ts @@ -0,0 +1,24 @@ +import type { Dayjs } from "dayjs"; +import * as yup from "yup"; +declare module "yup" { + interface StringSchema< + TType extends Maybe = string | undefined, + TContext extends AnyObject = AnyObject, + TOut extends TType = TType + > extends yup.BaseSchema { + emptyAsUndefined(): StringSchema; + } + interface ArraySchema< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T extends AnySchema | Lazy, + C extends AnyObject = AnyObject, + TIn extends Maybe[]> = TypeOf[] | undefined, + TOut extends Maybe[]> = Asserts[] | Optionals + > extends BaseSchema { + isItBeforeNow(): ArraySchema; + isOfferValidityDatesValid(): ArraySchema; + isRedemptionDatesValid(): ArraySchema; + } +} + +export default yup; diff --git a/src/lib/utils/hooks/offer/useCreateOffers.tsx b/src/lib/utils/hooks/offer/useCreateOffers.tsx new file mode 100644 index 000000000..5adc2c611 --- /dev/null +++ b/src/lib/utils/hooks/offer/useCreateOffers.tsx @@ -0,0 +1,332 @@ +import { offers, subgraph } from "@bosonprotocol/react-kit"; +import { useMutation } from "react-query"; +import { useAccount } from "wagmi"; + +import { authTokenTypes } from "../../../../components/modal/components/CreateProfile/Lens/const"; +import { useModal } from "../../../../components/modal/useModal"; +import { TOKEN_TYPES } from "../../../../components/product/utils"; +import { poll } from "../../../../pages/create-product/utils"; +import { + buildCondition, + CommonTermsOfSale +} from "../../../../pages/create-product/utils/buildCondition"; +import { useCoreSDK } from "../../useCoreSdk"; +import { useAddPendingTransaction } from "../transactions/usePendingTransactions"; +import { useCurrentSellers } from "../useCurrentSellers"; + +type OfferFieldsFragment = subgraph.OfferFieldsFragment; + +type UseCreateOffersProps = { + offersToCreate: offers.CreateOfferArgs[]; + isMultiVariant: boolean; + tokenGatedInfo?: CommonTermsOfSale | null; + conditionDecimals?: number; + onGetExchangeTokenDecimals?: (decimals: number | undefined) => unknown; + onCreatedOffersWithVariants?: (arg0: { + firstOffer: OfferFieldsFragment; + }) => void; + onCreatedSingleOffers?: (arg0: { offer: OfferFieldsFragment }) => void; +}; + +export function useCreateOffers() { + const coreSDK = useCoreSDK(); + const { sellers } = useCurrentSellers(); + const { address } = useAccount(); + const { showModal, hideModal } = useModal(); + const addPendingTransaction = useAddPendingTransaction(); + const isMetaTx = Boolean(coreSDK.isMetaTxConfigSet && address); + return useMutation( + async ({ + offersToCreate, + isMultiVariant, + tokenGatedInfo, + conditionDecimals, + onGetExchangeTokenDecimals, + onCreatedOffersWithVariants, + onCreatedSingleOffers + }: UseCreateOffersProps) => { + const isTokenGated = !!tokenGatedInfo; + const onBeforeBuildCondition = async () => { + let decimalsLocal: number | undefined = conditionDecimals; + if ( + tokenGatedInfo?.tokenContract && + tokenGatedInfo.tokenType?.value === TOKEN_TYPES[0].value + ) { + try { + const { decimals: tokenDecimals } = + await coreSDK.getExchangeTokenInfo(tokenGatedInfo.tokenContract); + decimalsLocal = tokenDecimals; + onGetExchangeTokenDecimals?.(decimalsLocal); + } catch (error) { + decimalsLocal = undefined; + onGetExchangeTokenDecimals?.(decimalsLocal); + } + } + return decimalsLocal; + }; + showModal("WAITING_FOR_CONFIRMATION"); + const hasSellerAccount = !!sellers?.length; + const seller = address + ? { + operator: address, + admin: address, + treasury: address, + clerk: address, + contractUri: "ipfs://sample", + royaltyPercentage: "0", + authTokenId: "0", + authTokenType: authTokenTypes.NONE + } + : null; + let txResponse; + if (isMultiVariant) { + if (!hasSellerAccount && seller) { + if (isMetaTx) { + // createSeller with meta-transaction + const nonce = Date.now(); + const { r, s, v, functionName, functionSignature } = + await coreSDK.signMetaTxCreateSeller({ + createSellerArgs: seller, + nonce + }); + txResponse = await coreSDK.relayMetaTransaction({ + functionName, + functionSignature, + sigR: r, + sigS: s, + sigV: v, + nonce + }); + } else { + txResponse = await coreSDK.createSeller(seller); + } + showModal("TRANSACTION_SUBMITTED", { + action: "Create seller", + txHash: txResponse.hash + }); + addPendingTransaction({ + type: subgraph.EventType.SellerCreated, + hash: txResponse.hash, + isMetaTx, + accountType: "Seller" + }); + await txResponse.wait(); + showModal("WAITING_FOR_CONFIRMATION"); + } + if (isMetaTx) { + // createOfferBatch with meta-transaction + const nonce = Date.now(); + const { r, s, v, functionName, functionSignature } = + await coreSDK.signMetaTxCreateOfferBatch({ + createOffersArgs: offersToCreate, + nonce + }); + txResponse = await coreSDK.relayMetaTransaction({ + functionName, + functionSignature, + sigR: r, + sigS: s, + sigV: v, + nonce + }); + } else { + txResponse = await coreSDK.createOfferBatch(offersToCreate); + } + showModal("TRANSACTION_SUBMITTED", { + action: "Create offer with variants", + txHash: txResponse.hash + }); + addPendingTransaction({ + type: subgraph.EventType.OfferCreated, + hash: txResponse.hash, + isMetaTx, + accountType: "Seller" + }); + const txReceipt = await txResponse.wait(); + const offerIds = coreSDK.getCreatedOfferIdsFromLogs(txReceipt.logs); + + if (isTokenGated) { + showModal("WAITING_FOR_CONFIRMATION"); + const decimals = await onBeforeBuildCondition(); + const condition = buildCondition(tokenGatedInfo, decimals); + + if (isMetaTx) { + const nonce = Date.now(); + const { r, s, v, functionName, functionSignature } = + await coreSDK.signMetaTxCreateGroup({ + createGroupArgs: { offerIds, ...condition }, + nonce + }); + txResponse = await coreSDK.relayMetaTransaction({ + functionName, + functionSignature, + sigR: r, + sigS: s, + sigV: v, + nonce + }); + } else { + txResponse = await coreSDK.createGroup({ offerIds, ...condition }); + } + showModal("TRANSACTION_SUBMITTED", { + action: "Create condition group for offers", + txHash: txResponse.hash + }); + await txResponse.wait(); + } + let createdOffers: OfferFieldsFragment[] | null = null; + await poll( + async () => { + createdOffers = ( + await Promise.all( + offerIds.map((offerId) => + coreSDK.getOfferById(offerId as string) + ) + ) + ).filter((offer) => !!offer); + return createdOffers; + }, + (offers) => { + return offers.length !== offerIds.length; + }, + 500 + ); + const [firstOffer] = createdOffers as unknown as OfferFieldsFragment[]; + onCreatedOffersWithVariants?.({ + firstOffer + }); + } else { + // no variants + const [offerData] = offersToCreate; + if (isMetaTx) { + // meta-transaction + if (!hasSellerAccount && seller) { + // createSeller with meta-transaction + const nonce = Date.now(); + const { r, s, v, functionName, functionSignature } = + await coreSDK.signMetaTxCreateSeller({ + createSellerArgs: seller, + nonce + }); + const createSellerResponse = await coreSDK.relayMetaTransaction({ + functionName, + functionSignature, + sigR: r, + sigS: s, + sigV: v, + nonce + }); + showModal("TRANSACTION_SUBMITTED", { + action: "Create seller", + txHash: createSellerResponse.hash + }); + addPendingTransaction({ + type: subgraph.EventType.SellerCreated, + hash: createSellerResponse.hash, + isMetaTx, + accountType: "Seller" + }); + await createSellerResponse.wait(); + showModal("WAITING_FOR_CONFIRMATION"); + } + // createOffer with meta-transaction + const nonce = Date.now(); + if (isTokenGated) { + const decimals = await onBeforeBuildCondition(); + const condition = buildCondition(tokenGatedInfo, decimals); + const { r, s, v, functionName, functionSignature } = + await coreSDK.signMetaTxCreateOfferWithCondition({ + offerToCreate: offerData, + condition, + nonce + }); + txResponse = await coreSDK.relayMetaTransaction({ + functionName, + functionSignature, + sigR: r, + sigS: s, + sigV: v, + nonce + }); + } else { + const { r, s, v, functionName, functionSignature } = + await coreSDK.signMetaTxCreateOffer({ + createOfferArgs: offerData, + nonce + }); + txResponse = await coreSDK.relayMetaTransaction({ + functionName, + functionSignature, + sigR: r, + sigS: s, + sigV: v, + nonce + }); + } + } else { + // no meta tx + if (isTokenGated) { + const decimals = await onBeforeBuildCondition(); + const condition = buildCondition(tokenGatedInfo, decimals); + txResponse = + !hasSellerAccount && seller + ? await coreSDK.createSellerAndOfferWithCondition( + seller, + offerData, + condition + ) + : await coreSDK.createOfferWithCondition(offerData, condition); + } else { + txResponse = + !hasSellerAccount && seller + ? await coreSDK.createSellerAndOffer(seller, offerData) + : await coreSDK.createOffer(offerData); + } + } + showModal("TRANSACTION_SUBMITTED", { + action: "Create offer", + txHash: txResponse.hash + }); + + addPendingTransaction({ + type: subgraph.EventType.OfferCreated, + hash: txResponse.hash, + isMetaTx, + accountType: "Seller" + }); + + if (!hasSellerAccount && seller) { + addPendingTransaction({ + type: subgraph.EventType.SellerCreated, + hash: txResponse.hash, + isMetaTx, + accountType: "Seller" + }); + } + + const txReceipt = await txResponse.wait(); + const offerId = coreSDK.getCreatedOfferIdFromLogs(txReceipt.logs); + let createdOffer: OfferFieldsFragment | null = null; + await poll( + async () => { + createdOffer = await coreSDK.getOfferById(offerId as string); + return createdOffer; + }, + (offer) => { + return !offer; + }, + 500 + ); + if (!createdOffer) { + return; + } + + onCreatedSingleOffers?.({ + offer: createdOffer + }); + } + + hideModal(); + } + ); +} diff --git a/src/lib/utils/hooks/useDidMountEffect.ts b/src/lib/utils/hooks/useDidMountEffect.ts new file mode 100644 index 000000000..b43583c64 --- /dev/null +++ b/src/lib/utils/hooks/useDidMountEffect.ts @@ -0,0 +1,14 @@ +import { useEffect, useRef } from "react"; + +type Params = Parameters; + +// to have a 'useEffect' that only changes when dependencies change (instead of that + initial render) +export const useDidMountEffect = (func: Params[0], deps: Params[1]) => { + const didMount = useRef(false); + + useEffect(() => { + if (didMount.current) func(); + else didMount.current = true; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps); +}; diff --git a/src/lib/validation/index.ts b/src/lib/validation/index.ts index 5a4f9c452..781c39ca4 100644 --- a/src/lib/validation/index.ts +++ b/src/lib/validation/index.ts @@ -1,5 +1,4 @@ -// eslint-disable-next-line -// @ts-nocheck +import type { Dayjs } from "dayjs"; import * as Yup from "yup"; import disputePeriodValue from "./disputePeriodValue"; @@ -9,17 +8,21 @@ import isOfferValidityDatesValid from "./isOfferValidityDatesValid"; import isRedemptionDatesValid from "./isRedemptionDatesValid"; import returnPeriodValue from "./returnPeriodValue"; -Yup.addMethod( - Yup.mixed, +Yup.addMethod>>( + Yup.array, "isRedemptionDatesValid", isRedemptionDatesValid ); -Yup.addMethod( - Yup.mixed, +Yup.addMethod>>( + Yup.array, "isOfferValidityDatesValid", isOfferValidityDatesValid ); -Yup.addMethod(Yup.mixed, "isItBeforeNow", isItBeforeNow); +Yup.addMethod>>( + Yup.array, + "isItBeforeNow", + isItBeforeNow +); Yup.addMethod( Yup.string, "disputePeriodValue", diff --git a/src/lib/validation/isItBeforeNow.ts b/src/lib/validation/isItBeforeNow.ts index 0698fe25d..d0feb143b 100644 --- a/src/lib/validation/isItBeforeNow.ts +++ b/src/lib/validation/isItBeforeNow.ts @@ -3,6 +3,9 @@ import dayjs from "dayjs"; function isItBeforeNow() { return this.test("isItBeforeNow", function (value: (Dayjs | null)[]) { + if (!value) { + return false; + } const startBeforeNow = value[0] instanceof dayjs ? value[0]?.isBefore(dayjs()) diff --git a/src/lib/validation/isOfferValidityDatesValid.ts b/src/lib/validation/isOfferValidityDatesValid.ts index 3fe313e06..e1b471d7b 100644 --- a/src/lib/validation/isOfferValidityDatesValid.ts +++ b/src/lib/validation/isOfferValidityDatesValid.ts @@ -5,6 +5,9 @@ function isOfferValidityDatesValid() { return this.test( "isOfferValidityDatesValid", function (value: (Dayjs | null)[]) { + if (!value) { + return false; + } const rpValue: (Dayjs | null)[] = this.parent.redemptionPeriod; const doesItEndBefore = rpValue[1] instanceof dayjs diff --git a/src/lib/validation/isRedemptionDatesValid.ts b/src/lib/validation/isRedemptionDatesValid.ts index 6b798638d..76c55bf83 100644 --- a/src/lib/validation/isRedemptionDatesValid.ts +++ b/src/lib/validation/isRedemptionDatesValid.ts @@ -3,8 +3,11 @@ import dayjs from "dayjs"; function isRedemptionDatesValid() { return this.test( - "isOfferValidityDatesValid", + "isRedemptionDatesValid", function (value: (Dayjs | null)[]) { + if (!value) { + return false; + } const ovValue = this.parent.offerValidityPeriod; const doesItEndBefore = value[1] instanceof dayjs diff --git a/src/pages/chat/ChatProvider/ChatContext.ts b/src/pages/chat/ChatProvider/ChatContext.ts index a544db8ff..2456a12fe 100644 --- a/src/pages/chat/ChatProvider/ChatContext.ts +++ b/src/pages/chat/ChatProvider/ChatContext.ts @@ -5,10 +5,12 @@ export const Context = createContext<{ bosonXmtp: BosonXmtpClient | undefined; initialize: Dispatch>; envName: string; + error: unknown; isInitializing: boolean; }>({ bosonXmtp: undefined, initialize: () => console.log("initialize has not been defined"), + error: null, envName: "", isInitializing: false }); diff --git a/src/pages/chat/ChatProvider/ChatProvider.tsx b/src/pages/chat/ChatProvider/ChatProvider.tsx index 11bfee8e6..248262568 100644 --- a/src/pages/chat/ChatProvider/ChatProvider.tsx +++ b/src/pages/chat/ChatProvider/ChatProvider.tsx @@ -14,6 +14,7 @@ export default function ChatProvider({ children }: Props) { const { data: signer } = useSigner(); const [initialize, setInitialized] = useState(0); const [isLoading, setLoading] = useState(false); + const [error, setError] = useState(); const [bosonXmtp, setBosonXmtp] = useState(); useEffect(() => { if (signer && initialize && !bosonXmtp) { @@ -25,8 +26,12 @@ export default function ChatProvider({ children }: Props) { ) .then((bosonClient) => { setBosonXmtp(bosonClient); + setError(null); + }) + .catch((error) => { + console.error(error); + setError(error); }) - .catch(console.error) .finally(() => setLoading(false)); } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -38,6 +43,7 @@ export default function ChatProvider({ children }: Props) { initialize: () => { setInitialized((prev) => prev + 1); }, + error, envName, isInitializing: isLoading }} diff --git a/src/pages/create-product/CreateProduct.tsx b/src/pages/create-product/CreateProduct.tsx index 83ec0f0fa..259136338 100644 --- a/src/pages/create-product/CreateProduct.tsx +++ b/src/pages/create-product/CreateProduct.tsx @@ -24,12 +24,21 @@ function CreateProduct() { const showCreateProductDraftModal = useCallback(() => { if (store.shouldDisplayModal) { - showModal(modalTypes.CREATE_PRODUCT_DRAFT, { - title: "Draft", - chooseNew, - chooseDraft, - closable: false - }); + showModal( + modalTypes.CREATE_PRODUCT_DRAFT, + { + title: "Draft", + chooseNew, + chooseDraft, + closable: false + }, + "auto", + undefined, + { + xs: "100%", + s: "31.25rem" + } + ); } else { setDraftModalClosed(true); } diff --git a/src/pages/create-product/CreateProductInner.tsx b/src/pages/create-product/CreateProductInner.tsx index 914ca4436..b64336d43 100644 --- a/src/pages/create-product/CreateProductInner.tsx +++ b/src/pages/create-product/CreateProductInner.tsx @@ -8,7 +8,6 @@ import { subgraph } from "@bosonprotocol/react-kit"; import { parseUnits } from "@ethersproject/units"; -import type { Dayjs } from "dayjs"; import dayjs from "dayjs"; import localizedFormat from "dayjs/plugin/localizedFormat"; import { Form, Formik, FormikHelpers, FormikProps } from "formik"; @@ -21,13 +20,11 @@ import { generatePath, useLocation, useNavigate } from "react-router-dom"; import uuid from "react-uuid"; import { useAccount } from "wagmi"; dayjs.extend(localizedFormat); - import { BigNumber, ethers } from "ethers"; import { useEffect } from "react"; import { Token } from "../../components/convertion-rate/ConvertionRateContext"; import { FileProps } from "../../components/form/Upload/WithUploadToIpfs"; -import { authTokenTypes } from "../../components/modal/components/CreateProfile/Lens/const"; import { getLensCoverPictureUrl, getLensProfilePictureUrl, @@ -51,7 +48,7 @@ import { ProductRoutes } from "../../lib/routing/routes"; import { fetchIpfsBase64Media } from "../../lib/utils/base64"; import { useChatStatus } from "../../lib/utils/hooks/chat/useChatStatus"; import { Profile } from "../../lib/utils/hooks/lens/graphql/generated"; -import { useAddPendingTransaction } from "../../lib/utils/hooks/transactions/usePendingTransactions"; +import { useCreateOffers } from "../../lib/utils/hooks/offer/useCreateOffers"; import { useCurrentSellers } from "../../lib/utils/hooks/useCurrentSellers"; import { useIpfsStorage } from "../../lib/utils/hooks/useIpfsStorage"; import { useKeepQueryParamsNavigate } from "../../lib/utils/hooks/useKeepQueryParamsNavigate"; @@ -66,8 +63,7 @@ import { MultiStepsContainer, ProductLayoutContainer } from "./CreateProductInner.styles"; -import { createProductSteps, FIRST_STEP, poll } from "./utils"; -import { buildCondition } from "./utils/buildCondition"; +import { createProductSteps, FIRST_STEP } from "./utils"; import { validateDates } from "./utils/dataValidator"; import { CreateProductSteps } from "./utils/index"; @@ -394,7 +390,7 @@ function CreateProductInner({ [history, location, setCurrentStep] ); - const onCreateNewProject = () => { + const onCreateNew = () => { hideModal(); setCurrentStepWithHistory(FIRST_STEP); setIsPreviewVisible(false); @@ -415,10 +411,7 @@ function CreateProductInner({ const { address } = useAccount(); const { sellers, lens: lensProfiles } = useCurrentSellers(); - const addPendingTransaction = useAddPendingTransaction(); - - const hasSellerAccount = !!sellers?.length; - + const { mutateAsync: createOffers } = useCreateOffers(); const currentOperator = sellers.find((seller) => { return seller?.operator.toLowerCase() === address?.toLowerCase(); }); @@ -482,7 +475,7 @@ function CreateProductInner({ }, hasMultipleVariants: !!values.productVariants.variants.length, // these are the ones that we already had before - onCreateNewProject: onCreateNewProject, + onCreateNew: onCreateNew, onViewMyItem: () => onViewMyItem(metadataInfo.product?.uuid) }, "auto" @@ -872,330 +865,47 @@ function CreateProductInner({ }); offersToCreate.push(offerData); } - - showModal("WAITING_FOR_CONFIRMATION"); - const isMetaTx = Boolean(coreSDK.isMetaTxConfigSet && address); - const seller = address - ? { - operator: address, - admin: address, - treasury: address, - clerk: address, - contractUri: "ipfs://sample", - royaltyPercentage: "0", - authTokenId: "0", - authTokenType: authTokenTypes.NONE - } - : null; const isTokenGated = commonTermsOfSale.tokenGatedOffer.value === "true"; - let txResponse; - if (isMultiVariant) { - if (!hasSellerAccount && seller) { - if (isMetaTx) { - // createSeller with meta-transaction - const nonce = Date.now(); - const { r, s, v, functionName, functionSignature } = - await coreSDK.signMetaTxCreateSeller({ - createSellerArgs: seller, - nonce - }); - txResponse = await coreSDK.relayMetaTransaction({ - functionName, - functionSignature, - sigR: r, - sigS: s, - sigV: v, - nonce - }); - } else { - txResponse = await coreSDK.createSeller(seller); - } - showModal("TRANSACTION_SUBMITTED", { - action: "Create seller", - txHash: txResponse.hash - }); - addPendingTransaction({ - type: subgraph.EventType.SellerCreated, - hash: txResponse.hash, - isMetaTx, - accountType: "Seller" - }); - await txResponse.wait(); - showModal("WAITING_FOR_CONFIRMATION"); - } - if (isMetaTx) { - // createOfferBatch with meta-transaction - const nonce = Date.now(); - const { r, s, v, functionName, functionSignature } = - await coreSDK.signMetaTxCreateOfferBatch({ - createOffersArgs: offersToCreate, - nonce - }); - txResponse = await coreSDK.relayMetaTransaction({ - functionName, - functionSignature, - sigR: r, - sigS: s, - sigV: v, - nonce - }); - } else { - txResponse = await coreSDK.createOfferBatch(offersToCreate); - } - showModal("TRANSACTION_SUBMITTED", { - action: "Create offer with variants", - txHash: txResponse.hash - }); - addPendingTransaction({ - type: subgraph.EventType.OfferCreated, - hash: txResponse.hash, - isMetaTx, - accountType: "Seller" - }); - const txReceipt = await txResponse.wait(); - const offerIds = coreSDK.getCreatedOfferIdsFromLogs(txReceipt.logs); - - if (isTokenGated) { - showModal("WAITING_FOR_CONFIRMATION"); - if ( - commonTermsOfSale?.tokenContract && - commonTermsOfSale.tokenType?.value === TOKEN_TYPES[0].value - ) { - try { - const { decimals: decimalsLocal } = - await coreSDK.getExchangeTokenInfo( - commonTermsOfSale.tokenContract - ); - setDecimals(decimalsLocal); - } catch (error) { - setDecimals(undefined); - } - } - const condition = buildCondition(commonTermsOfSale, decimals); - - if (isMetaTx) { - const nonce = Date.now(); - const { r, s, v, functionName, functionSignature } = - await coreSDK.signMetaTxCreateGroup({ - createGroupArgs: { offerIds, ...condition }, - nonce - }); - txResponse = await coreSDK.relayMetaTransaction({ - functionName, - functionSignature, - sigR: r, - sigS: s, - sigV: v, - nonce - }); - } else { - txResponse = await coreSDK.createGroup({ offerIds, ...condition }); - } - showModal("TRANSACTION_SUBMITTED", { - action: "Create condition group for offers", - txHash: txResponse.hash - }); - await txResponse.wait(); - } - let createdOffers: OfferFieldsFragment[] | null = null; - await poll( - async () => { - createdOffers = ( - await Promise.all( - offerIds.map((offerId) => - coreSDK.getOfferById(offerId as string) - ) - ) - ).filter((offer) => !!offer); - return createdOffers; - }, - (offers) => { - return offers.length !== offerIds.length; - }, - 500 - ); - const [firstOffer] = createdOffers as unknown as OfferFieldsFragment[]; - toast((t) => ( - { - handleOpenSuccessModal({ - offerInfo: firstOffer || ({} as subgraph.OfferFieldsFragment), - values - }); - }} - /> - )); - } else { - const [offerData] = offersToCreate; - if (isMetaTx) { - // meta-transaction - if (!hasSellerAccount && seller) { - // createSeller with meta-transaction - const nonce = Date.now(); - const { r, s, v, functionName, functionSignature } = - await coreSDK.signMetaTxCreateSeller({ - createSellerArgs: seller, - nonce - }); - const createSellerResponse = await coreSDK.relayMetaTransaction({ - functionName, - functionSignature, - sigR: r, - sigS: s, - sigV: v, - nonce - }); - showModal("TRANSACTION_SUBMITTED", { - action: "Create seller", - txHash: createSellerResponse.hash - }); - addPendingTransaction({ - type: subgraph.EventType.SellerCreated, - hash: createSellerResponse.hash, - isMetaTx, - accountType: "Seller" - }); - await createSellerResponse.wait(); - showModal("WAITING_FOR_CONFIRMATION"); - } - // createOffer with meta-transaction - const nonce = Date.now(); - if (!isTokenGated) { - const { r, s, v, functionName, functionSignature } = - await coreSDK.signMetaTxCreateOffer({ - createOfferArgs: offerData, - nonce - }); - txResponse = await coreSDK.relayMetaTransaction({ - functionName, - functionSignature, - sigR: r, - sigS: s, - sigV: v, - nonce - }); - } else { - if ( - commonTermsOfSale?.tokenContract && - commonTermsOfSale.tokenType?.value === TOKEN_TYPES[0].value - ) { - try { - const { decimals: decimalsLocal } = - await coreSDK.getExchangeTokenInfo( - commonTermsOfSale.tokenContract - ); - setDecimals(decimalsLocal); - } catch (error) { - setDecimals(undefined); - } - } - const condition = buildCondition(commonTermsOfSale, decimals); - const { r, s, v, functionName, functionSignature } = - await coreSDK.signMetaTxCreateOfferWithCondition({ - offerToCreate: offerData, - condition, - nonce - }); - txResponse = await coreSDK.relayMetaTransaction({ - functionName, - functionSignature, - sigR: r, - sigS: s, - sigV: v, - nonce - }); - } - } else { - if (isTokenGated) { - if ( - commonTermsOfSale?.tokenContract && - commonTermsOfSale.tokenType?.value === TOKEN_TYPES[0].value - ) { - try { - const { decimals: decimalsLocal } = - await coreSDK.getExchangeTokenInfo( - commonTermsOfSale.tokenContract - ); - - setDecimals(decimalsLocal); - } catch (error) { - setDecimals(undefined); - } - } - const condition = buildCondition(commonTermsOfSale, decimals); - txResponse = - !hasSellerAccount && seller - ? await coreSDK.createSellerAndOfferWithCondition( - seller, - offerData, - condition - ) - : await coreSDK.createOfferWithCondition(offerData, condition); - } else { - txResponse = - !hasSellerAccount && seller - ? await coreSDK.createSellerAndOffer(seller, offerData) - : await coreSDK.createOffer(offerData); - } - } - showModal("TRANSACTION_SUBMITTED", { - action: "Create offer", - txHash: txResponse.hash - }); - - addPendingTransaction({ - type: subgraph.EventType.OfferCreated, - hash: txResponse.hash, - isMetaTx, - accountType: "Seller" - }); - - if (!hasSellerAccount && seller) { - addPendingTransaction({ - type: subgraph.EventType.SellerCreated, - hash: txResponse.hash, - isMetaTx, - accountType: "Seller" - }); - } - - const txReceipt = await txResponse.wait(); - const offerId = coreSDK.getCreatedOfferIdFromLogs(txReceipt.logs); - let createdOffer: OfferFieldsFragment | null = null; - await poll( - async () => { - createdOffer = await coreSDK.getOfferById(offerId as string); - return createdOffer; - }, - (offer) => { - return !offer; - }, - 500 - ); - if (!createdOffer) { - return; + await createOffers({ + isMultiVariant, + offersToCreate, + tokenGatedInfo: isTokenGated ? commonTermsOfSale : null, + conditionDecimals: decimals, + onGetExchangeTokenDecimals: setDecimals, + onCreatedOffersWithVariants: ({ firstOffer }) => { + toast((t) => ( + { + handleOpenSuccessModal({ + offerInfo: firstOffer || ({} as subgraph.OfferFieldsFragment), + values + }); + }} + /> + )); + }, + onCreatedSingleOffers: ({ offer: createdOffer }) => { + toast((t) => ( + { + handleOpenSuccessModal({ + offerInfo: + createdOffer || ({} as subgraph.OfferFieldsFragment), + values + }); + }} + /> + )); } - toast((t) => ( - { - handleOpenSuccessModal({ - offerInfo: createdOffer || ({} as subgraph.OfferFieldsFragment), - values - }); - }} - /> - )); - } - - hideModal(); + }); } catch (error: any) { // TODO: FAILURE MODAL console.error("error->", error.errors ?? error); - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } }; @@ -1221,11 +931,11 @@ function CreateProductInner({ [coreTermsOfSaleKey]: { ...values[coreTermsOfSaleKey], redemptionPeriod: - values?.[coreTermsOfSaleKey]?.redemptionPeriod?.map((d: Dayjs) => + values?.[coreTermsOfSaleKey]?.redemptionPeriod?.map((d) => dayjs(d).format() ) ?? [], offerValidityPeriod: - values?.[coreTermsOfSaleKey]?.offerValidityPeriod?.map((d: Dayjs) => + values?.[coreTermsOfSaleKey]?.offerValidityPeriod?.map((d) => dayjs(d).format() ) ?? [] } diff --git a/src/pages/create-product/utils/buildCondition.ts b/src/pages/create-product/utils/buildCondition.ts index 508994bf0..24e2fab9a 100644 --- a/src/pages/create-product/utils/buildCondition.ts +++ b/src/pages/create-product/utils/buildCondition.ts @@ -7,10 +7,22 @@ import { utils } from "ethers"; import { CreateProductForm } from "../../../components/product/utils"; +type JointTermsOfSale = + | CreateProductForm["coreTermsOfSale"] + | CreateProductForm["variantsCoreTermsOfSale"]; + +export type CommonTermsOfSale = Pick< + JointTermsOfSale, + | "tokenId" + | "minBalance" + | "tokenType" + | "tokenCriteria" + | "tokenContract" + | "maxCommits" +>; + export const buildCondition = ( - commonTermsOfSale: - | CreateProductForm["coreTermsOfSale"] - | CreateProductForm["variantsCoreTermsOfSale"], + commonTermsOfSale: CommonTermsOfSale, decimals?: number ): ConditionStruct => { let tokenType: TokenType = TokenType.FungibleToken; diff --git a/src/pages/create-product/utils/dataValidator.ts b/src/pages/create-product/utils/dataValidator.ts index 8d093edce..fb37321f4 100644 --- a/src/pages/create-product/utils/dataValidator.ts +++ b/src/pages/create-product/utils/dataValidator.ts @@ -1,3 +1,5 @@ +import type { Dayjs } from "dayjs"; + interface ReturnValues { validFromDateInMS: number; validUntilDateInMS: number; @@ -8,34 +10,30 @@ export const validateDates = ({ offerValidityPeriod, redemptionPeriod }: { - offerValidityPeriod: Array<{ $d: string }>; - redemptionPeriod: Array<{ $d: string }>; + offerValidityPeriod: Array; + redemptionPeriod: Array; }): ReturnValues => { const now = Date.now(); const numberMinutesAdd = 5; - let validFromDateInMS = Date.parse(offerValidityPeriod[0].$d); - + let validFromDateInMS = offerValidityPeriod[0].toDate().getTime(); if (validFromDateInMS < now) { validFromDateInMS = new Date(now + numberMinutesAdd * 60000).getTime(); } - let validUntilDateInMS = Date.parse(offerValidityPeriod[1].$d); - + let validUntilDateInMS = offerValidityPeriod[1].toDate().getTime(); if (validUntilDateInMS < now) { validUntilDateInMS = new Date(now + numberMinutesAdd * 2 * 60000).getTime(); } - let voucherRedeemableFromDateInMS = Date.parse(redemptionPeriod[0].$d); - + let voucherRedeemableFromDateInMS = redemptionPeriod[0].toDate().getTime(); if (voucherRedeemableFromDateInMS < now) { voucherRedeemableFromDateInMS = new Date( now + numberMinutesAdd * 60000 ).getTime(); } - let voucherRedeemableUntilDateInMS = Date.parse(redemptionPeriod[1].$d); - + let voucherRedeemableUntilDateInMS = redemptionPeriod[1].toDate().getTime(); if (voucherRedeemableUntilDateInMS < now) { voucherRedeemableUntilDateInMS = new Date( now + numberMinutesAdd * 2 * 60000 diff --git a/src/pages/create-product/utils/index.tsx b/src/pages/create-product/utils/index.tsx index 46cd56709..32773d878 100644 --- a/src/pages/create-product/utils/index.tsx +++ b/src/pages/create-product/utils/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import ConfirmProductDetails from "../../../components/product/ConfirmProductDetails"; -import CoreTermsOfSale from "../../../components/product/CoreTermsOfSale"; +import CoreTermsOfSale from "../../../components/product/coreTermsOfSale/CoreTermsOfSale"; import ProductImages from "../../../components/product/ProductImages"; import ProductInformation from "../../../components/product/ProductInformation"; import ProductType from "../../../components/product/ProductType"; diff --git a/src/pages/dispute-centre/DisputeCentre.tsx b/src/pages/dispute-centre/DisputeCentre.tsx index a8dc4f813..a2978dff4 100644 --- a/src/pages/dispute-centre/DisputeCentre.tsx +++ b/src/pages/dispute-centre/DisputeCentre.tsx @@ -303,7 +303,7 @@ function DisputeCentre() { (error as unknown as { code: string }).code === "ACTION_REJECTED"; if (hasUserRejectedTx) { - showModal("CONFIRMATION_FAILED"); + showModal("TRANSACTION_FAILED"); } setSubmitError(error as Error); From 2fcde456ceae87c29889ab057909ff027ccc3a49 Mon Sep 17 00:00:00 2001 From: Ludovic Levalleux Date: Thu, 27 Apr 2023 17:25:35 +0100 Subject: [PATCH 14/14] fix: allow the buyer to Retract a Dispute after it has been escalated --- .../chat/components/ExchangeSidePreview.tsx | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/pages/chat/components/ExchangeSidePreview.tsx b/src/pages/chat/components/ExchangeSidePreview.tsx index 9651d24a2..d00d8f9a8 100644 --- a/src/pages/chat/components/ExchangeSidePreview.tsx +++ b/src/pages/chat/components/ExchangeSidePreview.tsx @@ -418,7 +418,7 @@ export default function ExchangeSidePreview({
- {isInDispute && iAmTheBuyer && !isEscalated && !isRetracted ? ( + {isInDispute && iAmTheBuyer && !isRetracted ? ( Retract - - showModal( - "ESCALATE_MODAL", - { - title: "Escalate", - exchange: exchange, - refetch: refetchItAll - }, - "l" - ) - } - > - Escalate - + {!isEscalated ? ( + + showModal( + "ESCALATE_MODAL", + { + title: "Escalate", + exchange: exchange, + refetch: refetchItAll + }, + "l" + ) + } + > + Escalate + + ) : ( + <> + )} ) : isInRedeemed && iAmTheBuyer ? (