diff --git a/README.md b/README.md
index 96a73f8..50925f6 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,7 @@ type configDataType = {
contractAddress: string,
tokenId?: string,
amount?: number,
+ attributes?: { value: string, trait_type: string } [],
},
}[];
```
@@ -167,13 +168,14 @@ configDataType = {
contractAddress: string; // contractAddress of Token or NFT
tokenId?: string; // Token Id of the NFT (if req.)
amount?: number; // Amount of tokens (if req.)
+ attributes?: { value: string, trait_type: string } []; // Array of NFT Attributes (if req.)
};
}[]
```
### Methods
-There are currently 4 methods available , as follows :
+There are currently 5 methods available , as follows :
- `NFTWithTokenID` for NFT with a Specific Token ID from a collection, E.g. BAYC No. 8378
@@ -237,6 +239,22 @@ Need to add contractAddress and amount of the token
},
```
+- `NFTWithAttributes` for NFT with an Specific Attribute (trait type and value) from a collection, E.g. BAYC. Fur -> Pink.
+
+Need to add contractAddress and an array of attributes of the NFT
+
+```javascript
+{
+ path: "/page",
+ methodName: methods.NFTWithTokenID,
+ network: networks.Ethereum,
+ data: {
+ contractAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
+ attributes: [ { value: "Pink", trait_type: "Fur" } ]
+ },
+ },
+```
+
These can be accessed by importing methods
```javascript
@@ -245,6 +263,7 @@ export enum methods {
"NFTCollection",
"TOKEN",
"TOKENwithAmount",
+ "NFTWithAttributes"
}
```
@@ -270,7 +289,7 @@ export enum networks {
## Example
-Here is an example config File , for all the 4 types of Methods. Refer the same for more info -
+Here is an example config File , for all the 5 types of Methods. Refer the same for more info -
```javascript
import { configType, methods, networks } from "token-gating-sdk";
@@ -307,6 +326,17 @@ export const configData: configType = [
amount: 100000000,
},
},
+ {
+ path: "/privateattributes",
+ methodName: methods.NFTWithAttributes,
+ network: networks.Ethereum,
+ data: {
+ contractAddress: "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85",
+ attributes: [
+ { value: "letter", trait_type: "Character Set" },
+ ],
+ },
+ },
];
```
diff --git a/example/next-demo-app/config/config.ts b/example/next-demo-app/config/config.ts
index 72d2cd2..3f2df6f 100644
--- a/example/next-demo-app/config/config.ts
+++ b/example/next-demo-app/config/config.ts
@@ -32,4 +32,15 @@ export const configData: configType = [
amount: 100000000,
},
},
+ {
+ path: "/privateattributes",
+ methodName: methods.NFTWithAttributes,
+ network: networks.Ethereum,
+ data: {
+ contractAddress: "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85",
+ attributes: [
+ { value: "letter", trait_type: "Character Set" },
+ ],
+ },
+ },
];
diff --git a/example/next-demo-app/pages/privateattributes.js b/example/next-demo-app/pages/privateattributes.js
new file mode 100644
index 0000000..c364950
--- /dev/null
+++ b/example/next-demo-app/pages/privateattributes.js
@@ -0,0 +1,7 @@
+import React from "react";
+
+const privateattributes = () => {
+ return
privateattributes
;
+};
+
+export default privateattributes;
diff --git a/example/react-demo-app/src/config/config.ts b/example/react-demo-app/src/config/config.ts
index 72d2cd2..3f2df6f 100644
--- a/example/react-demo-app/src/config/config.ts
+++ b/example/react-demo-app/src/config/config.ts
@@ -32,4 +32,15 @@ export const configData: configType = [
amount: 100000000,
},
},
+ {
+ path: "/privateattributes",
+ methodName: methods.NFTWithAttributes,
+ network: networks.Ethereum,
+ data: {
+ contractAddress: "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85",
+ attributes: [
+ { value: "letter", trait_type: "Character Set" },
+ ],
+ },
+ },
];
diff --git a/example/react-demo-app/src/privateattributes.js b/example/react-demo-app/src/privateattributes.js
new file mode 100644
index 0000000..c364950
--- /dev/null
+++ b/example/react-demo-app/src/privateattributes.js
@@ -0,0 +1,7 @@
+import React from "react";
+
+const privateattributes = () => {
+ return privateattributes
;
+};
+
+export default privateattributes;
diff --git a/src/components/config/config.tsx b/src/components/config/config.tsx
index e49a2f1..fb169b9 100644
--- a/src/components/config/config.tsx
+++ b/src/components/config/config.tsx
@@ -10,6 +10,7 @@ export enum methods {
"NFTCollection",
"TOKEN",
"TOKENwithAmount",
+ "NFTWithAttributes"
}
export type configDataType = {
@@ -20,6 +21,7 @@ export type configDataType = {
contractAddress: string;
tokenId?: string;
amount?: number;
+ attributes?: { value: string, trait_type: string } [];
};
};
diff --git a/src/components/nextWrapper/nextWrapper.tsx b/src/components/nextWrapper/nextWrapper.tsx
index e2127d5..23ebc12 100644
--- a/src/components/nextWrapper/nextWrapper.tsx
+++ b/src/components/nextWrapper/nextWrapper.tsx
@@ -214,6 +214,53 @@ export const TokenGatingWrapper: React.FunctionComponent<
}
};
+ // 4. Owns a particular attribute from a particular NFT collection
+ // The trait should match trait type and value.
+ const checkNFTAttributes = async (
+ userAddress: string,
+ contractAddress: string,
+ attributes: { value: string, trait_type: string } [],
+ network: Network,
+ alchemyApiKey: string
+ ) => {
+ try {
+ const settings = {
+ apiKey: alchemyApiKey, // Replace with your Alchemy API Key.
+ network: network, // Replace with your network.
+ };
+
+ const alchemy = new Alchemy(settings);
+
+ console.log("Checking for the attributes");
+
+ const response = await alchemy.nft.getNftsForOwnerIterator(userAddress);
+ //console.log(response);
+
+ for await (const nft of response) {
+ if (nft.contract.address === contractAddress) {
+ const nftAttributes = nft.rawMetadata?.attributes;
+ if (nftAttributes) {
+ for (let x = 0; x < nftAttributes.length; x++) {
+ for (let y = 0; y < attributes.length; y++) {
+ if (
+ nftAttributes[x].trait_type === attributes[y].trait_type &&
+ nftAttributes[x].value === attributes[y].value
+ ) {
+ setAuthorised(true);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ setAuthorised(false);
+ return false;
+ } catch (error) {
+ console.log(error);
+ }
+ }
+
// check the URL and accordingly the condition
// Open up a ConnectWallet section in case there is no address
// Show a Loading icon when the details are loading
@@ -305,6 +352,18 @@ export const TokenGatingWrapper: React.FunctionComponent<
finalNetwork,
alchemyApiKey
);
+ } else if (configData.methodName == methods.NFTWithAttributes) {
+ if (!configData.data.attributes) {
+ console.log("INCORRECT INPUT DATA");
+ return;
+ }
+ response = await checkNFTAttributes(
+ address,
+ configData.data.contractAddress,
+ configData.data.attributes,
+ finalNetwork,
+ alchemyApiKey
+ );
}
console.log(response);
@@ -361,6 +420,11 @@ export const TokenGatingWrapper: React.FunctionComponent<
0,
8
)}`;
+ } else if (configData.methodName == methods.NFTWithAttributes) {
+ return `NFT from the Collection ${configData.data.contractAddress.slice(
+ 0,
+ 8
+ )} with the attributes ${configData.data.attributes.map(attribute => JSON.stringify(attribute)).join(",")}`;
} else {
return `all the conditions fulfilled`;
}
diff --git a/src/components/reactWrapper/reactWrapper.tsx b/src/components/reactWrapper/reactWrapper.tsx
index 65f6f24..4af9dc3 100644
--- a/src/components/reactWrapper/reactWrapper.tsx
+++ b/src/components/reactWrapper/reactWrapper.tsx
@@ -215,6 +215,53 @@ export const TokenGatingWrapper: React.FunctionComponent<
}
};
+ // 4. Owns a particular attribute from a particular NFT collection
+ // The trait should match trait type and value.
+ const checkNFTAttributes = async (
+ userAddress: string,
+ contractAddress: string,
+ attributes: { value: string, trait_type: string } [],
+ network: Network,
+ alchemyApiKey: string
+ ) => {
+ try {
+ const settings = {
+ apiKey: alchemyApiKey, // Replace with your Alchemy API Key.
+ network: network, // Replace with your network.
+ };
+
+ const alchemy = new Alchemy(settings);
+
+ console.log("Checking for the attributes");
+
+ const response = await alchemy.nft.getNftsForOwnerIterator(userAddress);
+ //console.log(response);
+
+ for await (const nft of response) {
+ if (nft.contract.address === contractAddress) {
+ const nftAttributes = nft.rawMetadata?.attributes;
+ if (nftAttributes) {
+ for (let x = 0; x < nftAttributes.length; x++) {
+ for (let y = 0; y < attributes.length; y++) {
+ if (
+ nftAttributes[x].trait_type === attributes[y].trait_type &&
+ nftAttributes[x].value === attributes[y].value
+ ) {
+ setAuthorised(true);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ setAuthorised(false);
+ return false;
+ } catch (error) {
+ console.log(error);
+ }
+ }
+
// check the URL and accordingly the condition
// Open up a ConnectWallet section in case there is no address
// Show a Loading icon when the details are loading
@@ -306,6 +353,18 @@ export const TokenGatingWrapper: React.FunctionComponent<
finalNetwork,
alchemyApiKey
);
+ } else if (configData.methodName == methods.NFTWithAttributes) {
+ if (!configData.data.attributes) {
+ console.log("INCORRECT INPUT DATA");
+ return;
+ }
+ response = await checkNFTAttributes(
+ address,
+ configData.data.contractAddress,
+ configData.data.attributes,
+ finalNetwork,
+ alchemyApiKey
+ );
}
console.log(response);
@@ -362,6 +421,11 @@ export const TokenGatingWrapper: React.FunctionComponent<
0,
8
)}`;
+ } else if (configData.methodName == methods.NFTWithAttributes) {
+ return `NFT from the Collection ${configData.data.contractAddress.slice(
+ 0,
+ 8
+ )} with the attributes ${configData.data.attributes.map(attribute => JSON.stringify(attribute)).join(",")}`;
} else {
return `all the conditions fulfilled`;
}
diff --git a/src/components/universalWrapper/universalWrapper.tsx b/src/components/universalWrapper/universalWrapper.tsx
index fce8d40..546e723 100644
--- a/src/components/universalWrapper/universalWrapper.tsx
+++ b/src/components/universalWrapper/universalWrapper.tsx
@@ -210,6 +210,53 @@ export const TokenGatingWrapper: React.FunctionComponent<
console.log(error);
}
};
+
+ // 4. Owns a particular attribute from a particular NFT collection
+ // The trait should match trait type and value.
+ const checkNFTAttributes = async (
+ userAddress: string,
+ contractAddress: string,
+ attributes: { value: string, trait_type: string } [],
+ network: Network,
+ alchemyApiKey: string
+ ) => {
+ try {
+ const settings = {
+ apiKey: alchemyApiKey, // Replace with your Alchemy API Key.
+ network: network, // Replace with your network.
+ };
+
+ const alchemy = new Alchemy(settings);
+
+ console.log("Checking for the attributes");
+
+ const response = await alchemy.nft.getNftsForOwnerIterator(userAddress);
+ //console.log(response);
+
+ for await (const nft of response) {
+ if (nft.contract.address === contractAddress) {
+ const nftAttributes = nft.rawMetadata?.attributes;
+ if (nftAttributes) {
+ for (let x = 0; x < nftAttributes.length; x++) {
+ for (let y = 0; y < attributes.length; y++) {
+ if (
+ nftAttributes[x].trait_type === attributes[y].trait_type &&
+ nftAttributes[x].value === attributes[y].value
+ ) {
+ setAuthorised(true);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ setAuthorised(false);
+ return false;
+ } catch (error) {
+ console.log(error);
+ }
+ }
// check the URL and accordingly the condition
// Open up a ConnectWallet section in case there is no address
@@ -302,6 +349,18 @@ export const TokenGatingWrapper: React.FunctionComponent<
finalNetwork,
alchemyApiKey
);
+ } else if (configData.methodName == methods.NFTWithAttributes) {
+ if (!configData.data.attributes) {
+ console.log("INCORRECT INPUT DATA");
+ return;
+ }
+ response = await checkNFTAttributes(
+ address,
+ configData.data.contractAddress,
+ configData.data.attributes,
+ finalNetwork,
+ alchemyApiKey
+ );
}
console.log(response);
@@ -358,6 +417,11 @@ export const TokenGatingWrapper: React.FunctionComponent<
0,
8
)}`;
+ } else if (configData.methodName == methods.NFTWithAttributes) {
+ return `NFT from the Collection ${configData.data.contractAddress.slice(
+ 0,
+ 8
+ )} with the attributes ${configData.data.attributes.map(attribute => JSON.stringify(attribute)).join(",")}`;
} else {
return `all the conditions fulfilled`;
}