Compare commits

..
Author SHA1 Message Date
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
20fb0d2300 Version Packages (#2847)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-04-24 16:48:07 -07:00
github-actions[bot]GitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
637c510f59 chore(chains): update chains (#2838)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-24 16:02:15 -07:00
YashandGitHub 2ae9a13b01 feat: add new airdrop extension (#2841) 2024-04-24 22:24:15 +00:00
Manan TankandGitHub 8d91e55eac Add missing lang for JSDoc code examples (#2851) 2024-04-24 21:24:30 +00:00
Manan TankandGitHub aa0b8c4465 Fix All Wallets UI in Connect (#2850) 2024-04-24 20:37:25 +00:00
Jonas DanielsandGitHub 41be954bd0 feat: Add celo chains to known op stack chains (#2848) 2024-04-24 11:55:40 -07:00
e8e3368fde Add extension: isERC20 (#2846)
Signed-off-by: Jonas Daniels <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2024-04-24 10:06:03 -07:00
Jonas DanielsandGitHub e1cd07c3e0 Version Packages (#2840) 2024-04-24 08:42:51 -07:00
Jonas DanielsandGitHub 8683449abb fix: Fix exportLocalWallet component rendering issue (#2845) 2024-04-23 22:16:13 -07:00
cfff7e838a Fix custom chain not used in wallet connection (#2768)
Co-authored-by: Jonas Daniels <[email protected]>
2024-04-24 04:48:23 +00:00
948f155e7c feat(transactions): add support for gasless transactions (#2818)
Co-authored-by: Joaquim Verges <[email protected]>
2024-04-23 21:56:19 -07:00
Joaquim VergesandGitHub d7e6671c0a fix: handle signature mint with price and currency (#2842) 2024-04-23 23:01:21 +00:00
560d8adafa feat: Add sign-in with Phone number in in-app wallet (#2679)
Signed-off-by: Winston Yeo <[email protected]>
Signed-off-by: Jonas Daniels <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
Co-authored-by: Manan Tank <[email protected]>
2024-04-23 22:57:06 +00:00
Manan TankandGitHub 3be61ddc52 Enable Buy Modal by default with useSendTransaction hook (#2839) 2024-04-23 13:58:14 -07:00
gregandGitHub a0e26a8c4f Contributing guide updates (#2833) 2024-04-23 12:54:38 -07:00
179 changed files with 9668 additions and 453 deletions
+50 -40
View File
@@ -1,9 +1,5 @@
# Contributing to thirdweb
You can find a full video tutorial on how to contribute to thirdweb below:
https://www.youtube.com/watch?v=TXsQ3qok3B0
## Getting Started
To get started, read the [How this repo works](#how-this-repo-works) section below to learn about the structure of this repo.
@@ -12,23 +8,19 @@ From there, you can take a look at our [Good First Issues](https://github.com/th
If you have any questions about the issue, feel free to ask on our [Discord server](https://discord.gg/thirdweb) in the `#contributors` channel; where you'll be able to get help from our team and other contributors.
<br/>
<br />
## How this repo works
[@thirdweb-dev/js](https://github.com/thirdweb-dev/js) is a monorepo, meaning it contains many projects within it.
We use [Turborepo](https://turbo.build/repo/docs) to manage the repository, and help speed up the [CI/CD](https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment) pipeline to ship to production faster 🚢. Turborepo is a project dependency, and doesn't need to be installed separately.
We use [Turborepo](https://turborepo.org/docs/getting-started) to manage the monorepo, and help speed up the [CI/CD](https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment) pipeline to ship to production faster 🚢.
We use [pnpm](https://pnpm.io) for package management across the repo. `pnpm` is similar to `npm` or `yarn` but with more efficient disk space usage.
You can see a quick outline of each of the projects within this repo below, each living within the [/packages](/packages) directory:
**With the v5 SDK, we've consolidated everything into a single project at [/packages/thirdweb](./packages/thirdweb). You can still find the legacy packages at [/legacy_packages](./legacy_packages).**
| Package | Description | Latest Version |
| ------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [/sdk](./legacy_packages/sdk) | Best in class web3 SDK for Browser, Node and Mobile apps | <a href="https://www.npmjs.com/package/@thirdweb-dev/sdk"><img src="https://img.shields.io/npm/v/@thirdweb-dev/sdk?color=red&label=npm&logo=npm" alt="npm version"/></a> |
| [/react](./legacy_packages/react) | Ultimate collection of React hooks for your web3 apps | <a href="https://www.npmjs.com/package/@thirdweb-dev/react"><img src="https://img.shields.io/npm/v/@thirdweb-dev/react?color=red&label=npm&logo=npm" alt="npm version"/></a> |
| [/auth](./legacy_packages/auth) | Best in class wallet authentication for Node backends | <a href="https://www.npmjs.com/package/@thirdweb-dev/auth"><img src="https://img.shields.io/npm/v/@thirdweb-dev/auth?color=red&label=npm&logo=npm" alt="npm version"/></a> |
| [/storage](./legacy_packages/storage) | Best in class decentralized storage SDK for Browser and Node | <a href="https://www.npmjs.com/package/@thirdweb-dev/storage"><img src="https://img.shields.io/npm/v/@thirdweb-dev/storage?color=red&label=npm&logo=npm" alt="npm version"/></a> |
| [/cli](./legacy_packages/cli) | Publish and deploy smart contracts without dealing with private keys | <a href="https://www.npmjs.com/package/thirdweb"><img src="https://img.shields.io/npm/v/thirdweb?color=red&label=npm&logo=npm" alt="npm version"/></a> |
This single package provides a performant & lightweight SDK to interact with any EVM chain across Node, React, and React Native. Learn more about how to use the thirdweb SDK in our [documentation](https://portal.thirdweb.com/typescript/v5).
<br />
## How to contribute
@@ -36,7 +28,7 @@ Let's explore how you can set up the repo on your local machine and start contri
This section requires some existing knowledge of [Git](https://git-scm.com/), [Node.js](https://nodejs.org/en/) and [pnpm](https://pnpm.io/).
<br/>
<br />
### Getting the repo
@@ -50,26 +42,50 @@ To begin:
3. Create a new branch on your fork to start working on your changes:
```
git checkout -b MY_BRANCH_NAME
```bash
git checkout -b <YOUR BRANCH NAME>
```
4. Install the dependencies:
```
```bash
pnpm install
```
If you are on windows, use the `--ignore-scripts` flag
```
```bash
pnpm install --ignore-scripts
```
Now you have got the repo on your local machine, and you're ready to start making your changes!
Now you have the repo on your local machine, and you're ready to start making your changes!
<br/>
### Test Your Changes
We use [yalc](https://github.com/wclr/yalc) to test changes locally.
#### Writing Unit Tests
Try to include unit test coverage with your changes where appropriate. We use `vitest` for testing, look for files with the `.test.ts` extension for examples of how to structure your unit tests.
To run your tests, run the following from the package directory (most likely /packages/thirdweb):
```bash
pnpm test:dev <YOUR TEST FILE PATH>
```
> Specifying your test file path is optional, but will save time by only running specific tests each time. Before opening your PR, run `pnpm test` from the monorepo root (without specifying your test file) to ensure your changes didn't break any existing tests.
#### Linting
We use a linter to maintain best practices across projects. Once your changes are complete (or periodically while making changes), run the linter with the following command from the repo root:
```bash
pnpm lint
```
If there are errors, try running `pnpm fix` to auto-fix any basic errors. Other linter errors, like missing documentation, will need to be fixed manually. See existing files for examples of inline documentation.
#### Creating a Local Test Project
You can use [yalc](https://github.com/wclr/yalc) to test changes on a local project.
Install the yalc CLI globally:
@@ -77,40 +93,35 @@ Install the yalc CLI globally:
pnpm add yalc -g
```
First, create a test project where you can experiment with your changes:
First, create a test project where you can experiment with your changes. This can be any node project that uses your changes.
You can create a basic starter project with the `sdk` and `react` packages installed using the CLI:
Push your local version to your `yalc` store with:
```bash
npx thirdweb create --app
pnpm build && pnpm push
```
Use `yalc` to link your local changes in the monorepo to the test project, by running the following command from your test repo:
Link your local changes in the monorepo to the test project by running the following command from your test repo:
```bash
yalc add @thirdweb-dev/react # Link the react package
yalc add @thirdweb-dev/sdk # Link the sdk package
# etc...
yalc add thirdweb
```
From the monorepo, run the following command to publish your local changes to the test project:
Now, each time you make a change to the monorepo, you can run `pnpm push` from the monorepo then `yalc update thirdweb` from your test project to publish your latest changes to the test project.
```bash
pnpm push
```
If your changes modify dependencies, you may need to reinstall dependencies on your test project with `pnpm install`
Now, each time you make a change to the monorepo, you can run `pnpm push` to publish your changes to the test project.
To make sure your latest changes are used, in your test project you may need to:
In your test project, you need to:
1. Delete the dependencies cache. If you're using Next.js, that is the `.next` directory, and if you're using CRA, that is the `node_modules/.cache` directory.
1. Delete the dependencies cache. If you're using Next.js, that's the `.next` directory, and if you're using CRA, that's the `node_modules/.cache` directory.
2. Restart the development server.
#### Testing from npm
You can also test your changes by publishing a dev package to npm and adding your package as you normally do in your projects.
Once you have your PR up you can add a comment with the text: `/release-pr`. This will trigger a GitHub action that will publish a dev version to npm.
**Once you have your PR up** you can add a comment with the text: `/release-pr`. This will trigger a GitHub action that will publish a dev version to npm.
You can see the action progress in GitHub's `Actions` tab, look for the workflow: `release-pr`.
@@ -154,9 +165,8 @@ git commit -am "My commit message"
3. Push your changes to the SDK:
```
git push origin MY_BRANCH_NAME
git push origin <YOUR BRANCH NAME>
```
4. Create a [pull request](https://www.atlassian.com/git/tutorials/making-a-pull-request) to the `main` branch of the official (not your fork) SDK repo.
It's helpful to tag PRs with `[SDK]`, `[REACT]`, `[AUTH]`, (the name of the package you're modifying) to indicate the package that you are engaging with.
+3
View File
@@ -8,5 +8,8 @@
"typescript.preferences.importModuleSpecifier": "relative",
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
+14
View File
@@ -1,5 +1,19 @@
# @thirdweb-dev/auth
## 4.1.68
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.5.10
## 4.1.67
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.5.9
## 4.1.66
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "4.1.66",
"version": "4.1.68",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/chains
## 0.1.100
### Patch Changes
- [#2838](https://github.com/thirdweb-dev/js/pull/2838) [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc) Thanks [@github-actions](https://github.com/apps/github-actions)! - Synced Chains Package
## 0.1.99
### Patch Changes
+1 -1
View File
@@ -24,7 +24,7 @@ export default {
"nativeCurrency": {
"name": "SMR",
"symbol": "SMR",
"decimals": 6
"decimals": 18
},
"networkId": 1073,
"rpc": [
+7 -1
View File
@@ -2,7 +2,13 @@ import type { Chain } from "../src/types";
export default {
"chain": "IOTA EVM",
"chainId": 1075,
"explorers": [],
"explorers": [
{
"name": "explorer",
"url": "https://explorer.evm.testnet.iotaledger.net",
"standard": "EIP3091"
}
],
"faucets": [
"https://evm-toolkit.evm.testnet.iotaledger.net"
],
+6
View File
@@ -4,6 +4,12 @@ export default {
"chainId": 1221,
"explorers": [],
"faucets": [],
"icon": {
"url": "ipfs://QmeC4mKGbBpwmLfFxUSsareWkSWJomevUmex8ajjxo1zHx",
"width": 500,
"height": 500,
"format": "png"
},
"infoURL": "https://www.cyclenetwork.io/",
"name": "Cycle Network Testnet",
"nativeCurrency": {
+1 -13
View File
@@ -6,22 +6,10 @@ export default {
{
"name": "BOASCAN",
"url": "https://boascan.io",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmW3CT4SHmso5dRJdsjR8GL1qmt79HkdAebCn2uNaWXFYh",
"width": 256,
"height": 257,
"format": "png"
}
"standard": "EIP3091"
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmW3CT4SHmso5dRJdsjR8GL1qmt79HkdAebCn2uNaWXFYh",
"width": 256,
"height": 257,
"format": "png"
},
"infoURL": "https://docs.bosagora.org",
"name": "BOSagora Mainnet",
"nativeCurrency": {
+1 -1
View File
@@ -31,7 +31,7 @@ export default {
"networkId": 224433,
"rpc": [
"https://224433.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://holeskyrpc1.conet.network"
"https://rpc.conet.network"
],
"shortName": "conet-holesky",
"slip44": 2147708081,
+45
View File
@@ -0,0 +1,45 @@
import type { Chain } from "../src/types";
export default {
"chain": "ETH",
"chainId": 27483,
"explorers": [
{
"name": "Nanon Sepolia Rollup Testnet Explorer",
"url": "https://sepolia-explorer.nanon.network",
"standard": "EIP3091"
}
],
"faucets": [],
"icon": {
"url": "ipfs://bafybeiduib2fygrwziqpy4yuqr6vvnd6elhahpigbcowcipjjhk6c3qiny",
"width": 400,
"height": 400,
"format": "png"
},
"infoURL": "https://www.nanon.network",
"name": "Nanon Sepolia",
"nativeCurrency": {
"name": "Sepolia Ether",
"symbol": "ETH",
"decimals": 18
},
"networkId": 27483,
"parent": {
"type": "L2",
"chain": "eip155-11155111",
"bridges": [
{
"url": "https://sepolia-bridge.nanon.network"
}
]
},
"rpc": [
"https://27483.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://sepolia-rpc.nanon.network"
],
"shortName": "Nanon-Testnet",
"slip44": 1,
"slug": "nanon-sepolia",
"testnet": true,
"title": "Nanon Sepolia Rollup Testnet"
} as const satisfies Chain;
+30
View File
@@ -0,0 +1,30 @@
import type { Chain } from "../src/types";
export default {
"chain": "Avalanche",
"chainId": 30406,
"explorers": [],
"faucets": [],
"features": [],
"icon": {
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
"width": 256,
"height": 256,
"format": "svg"
},
"infoURL": "https://avacloud.io",
"name": "MUGEN Testnet",
"nativeCurrency": {
"name": "MUGEN Testnet Token",
"symbol": "MGN",
"decimals": 18
},
"networkId": 30406,
"redFlags": [],
"rpc": [
"https://30406.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/mugen/testnet/rpc"
],
"shortName": "MUGEN Testnet",
"slug": "mugen-testnet",
"testnet": true
} as const satisfies Chain;
+30
View File
@@ -0,0 +1,30 @@
import type { Chain } from "../src/types";
export default {
"chain": "Avalanche",
"chainId": 38904,
"explorers": [],
"faucets": [],
"features": [],
"icon": {
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
"width": 256,
"height": 256,
"format": "svg"
},
"infoURL": "https://avacloud.io",
"name": "QaUser1490 Testnet",
"nativeCurrency": {
"name": "QaUser1490 Testnet Token",
"symbol": "PNK",
"decimals": 18
},
"networkId": 38904,
"redFlags": [],
"rpc": [
"https://38904.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
],
"shortName": "QaUser1490 Testnet",
"slug": "qauser1490-testnet",
"testnet": true
} as const satisfies Chain;
+1 -13
View File
@@ -6,22 +6,10 @@ export default {
{
"name": "MEVerse Chain Testnet Explorer",
"url": "https://testnet.meversescan.io",
"standard": "none",
"icon": {
"url": "ipfs://QmPuQ6gaCfUtNdRuaEDbdhot2m2KCy2ZHCJUvZXJAtdeyJ",
"width": 800,
"height": 800,
"format": "png"
}
"standard": "none"
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmPuQ6gaCfUtNdRuaEDbdhot2m2KCy2ZHCJUvZXJAtdeyJ",
"width": 800,
"height": 800,
"format": "png"
},
"infoURL": "https://www.meverse.sg",
"name": "MEVerse Chain Testnet",
"nativeCurrency": {
+30
View File
@@ -0,0 +1,30 @@
import type { Chain } from "../src/types";
export default {
"chain": "Avalanche",
"chainId": 65174,
"explorers": [],
"faucets": [],
"features": [],
"icon": {
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
"width": 256,
"height": 256,
"format": "svg"
},
"infoURL": "https://avacloud.io",
"name": "QaUser9821 Testnet",
"nativeCurrency": {
"name": "QaUser9821 Testnet Token",
"symbol": "HKL",
"decimals": 18
},
"networkId": 65174,
"redFlags": [],
"rpc": [
"https://65174.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
],
"shortName": "QaUser9821 Testnet",
"slug": "qauser9821-testnet",
"testnet": true
} as const satisfies Chain;
-6
View File
@@ -10,12 +10,6 @@ export default {
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmYbskrGpidbMwsJekTeLrr8Z6GA9q4Uxh7piS1F9BdWWv",
"width": 256,
"height": 256,
"format": "png"
},
"infoURL": "https://compverse.io",
"name": "Compverse Mainnet",
"nativeCurrency": {
+1 -13
View File
@@ -6,22 +6,10 @@ export default {
{
"name": "MEVerse Chain Explorer",
"url": "https://www.meversescan.io",
"standard": "none",
"icon": {
"url": "ipfs://QmPuQ6gaCfUtNdRuaEDbdhot2m2KCy2ZHCJUvZXJAtdeyJ",
"width": 800,
"height": 800,
"format": "png"
}
"standard": "none"
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmPuQ6gaCfUtNdRuaEDbdhot2m2KCy2ZHCJUvZXJAtdeyJ",
"width": 800,
"height": 800,
"format": "png"
},
"infoURL": "https://www.meverse.sg",
"name": "MEVerse Chain Mainnet",
"nativeCurrency": {
-6
View File
@@ -16,12 +16,6 @@ export default {
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmVhezQHkqSZ5Tvtsw18giA1yBjV1URSsBQ7HenUh6p6oC",
"width": 512,
"height": 512,
"format": "png"
},
"infoURL": "https://octa.space",
"name": "OctaSpace",
"nativeCurrency": {
+3 -2
View File
@@ -5,7 +5,7 @@ export default {
"explorers": [
{
"name": "explorer",
"url": "https://iota-evm.blockscout.com",
"url": "https://explorer.evm.iota.org",
"standard": "EIP3091",
"icon": {
"url": "ipfs://bafkreibky2sy6qhi6arktayvologkrgu5kudpgdxfkx4uosbvmstz7v4di",
@@ -32,7 +32,8 @@ export default {
"networkId": 8822,
"rpc": [
"https://8822.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://json-rpc.evm.iotaledger.net"
"https://json-rpc.evm.iotaledger.net",
"https://ws.json-rpc.evm.iotaledger.net"
],
"shortName": "iotaevm",
"slug": "iota-evm",
+30
View File
@@ -0,0 +1,30 @@
import type { Chain } from "../src/types";
export default {
"chain": "Avalanche",
"chainId": 88795,
"explorers": [],
"faucets": [],
"features": [],
"icon": {
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
"width": 256,
"height": 256,
"format": "svg"
},
"infoURL": "https://avacloud.io",
"name": "QaUser8230 Testnet",
"nativeCurrency": {
"name": "QaUser8230 Testnet Token",
"symbol": "GRB",
"decimals": 18
},
"networkId": 88795,
"redFlags": [],
"rpc": [
"https://88795.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
],
"shortName": "QaUser8230 Testnet",
"slug": "qauser8230-testnet",
"testnet": true
} as const satisfies Chain;
+1 -13
View File
@@ -6,22 +6,10 @@ export default {
{
"name": "Pepe Explorer",
"url": "https://explorer.pepenetwork.io",
"standard": "none",
"icon": {
"url": "ipfs://QmPX3uipdwd195z1MJff7uj8hpZdSuVvM5z47eiz2o7Gz5",
"width": 960,
"height": 944,
"format": "png"
}
"standard": "none"
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmPX3uipdwd195z1MJff7uj8hpZdSuVvM5z47eiz2o7Gz5",
"width": 960,
"height": 944,
"format": "png"
},
"infoURL": "https://pepenetwork.io",
"name": "PepeNetwork Mainnet",
"nativeCurrency": {
+45
View File
@@ -0,0 +1,45 @@
import type { Chain } from "../src/types";
export default {
"chain": "treasure",
"chainId": 978657,
"explorers": [
{
"name": "Treasurescan",
"url": "https://testnet.treasurescan.io/",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmbzZk23owb7grDEbEJLuxgUAqQVcHmdjsEkkCD7E9C5R9/Treasure_Primary_Icon%20-%20Karel%20Vuong.png",
"width": 512,
"height": 512,
"format": "png"
}
}
],
"faucets": [
"https://portal.treasure.lol/faucet"
],
"features": [],
"icon": {
"url": "ipfs://QmQYRpJAMyPt1DKz1iAuseX3puBZYmdGgFeaZCFDPhixXp",
"width": 512,
"height": 512,
"format": "svg"
},
"infoURL": "https://portal.treasure.lol",
"name": "Treasure Ruby",
"nativeCurrency": {
"name": "Testnet MAGIC",
"symbol": "MAGIC",
"decimals": 18
},
"networkId": 978657,
"redFlags": [],
"rpc": [
"https://978657.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-testnet.treasure.lol/http",
"wss://rpc-testnet.treasure.lol/ws"
],
"shortName": "MAGIC",
"slug": "treasure-ruby",
"testnet": true
} as const satisfies Chain;
-6
View File
@@ -10,12 +10,6 @@ export default {
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmZTWoZ3LvivSinaJ4aSwqU8pCXw8oSZNnUCh4wwXxtAoQ",
"width": 500,
"height": 500,
"format": "png"
},
"infoURL": "https://larissa.network",
"name": "Larissa Chain",
"nativeCurrency": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.99",
"version": "0.1.100",
"main": "dist/thirdweb-dev-chains.cjs.js",
"module": "dist/thirdweb-dev-chains.esm.js",
"exports": {
File diff suppressed because one or more lines are too long
+19
View File
@@ -1,5 +1,24 @@
# thirdweb
## 0.13.76
### Patch Changes
- Updated dependencies [[`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc)]:
- @thirdweb-dev/sdk@4.0.70
- @thirdweb-dev/chains@0.1.100
- @thirdweb-dev/wallets@2.5.10
- @thirdweb-dev/auth@4.1.68
## 0.13.75
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.69
- @thirdweb-dev/wallets@2.5.9
- @thirdweb-dev/auth@4.1.67
## 0.13.74
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/cli",
"main": "dist/cli/index.js",
"version": "0.13.74",
"version": "0.13.76",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+19
View File
@@ -1,5 +1,24 @@
# @thirdweb-dev/react-core
## 4.6.9
### Patch Changes
- Updated dependencies [[`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc)]:
- @thirdweb-dev/sdk@4.0.70
- @thirdweb-dev/chains@0.1.100
- @thirdweb-dev/wallets@2.5.10
- @thirdweb-dev/auth@4.1.68
## 4.6.8
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.69
- @thirdweb-dev/wallets@2.5.9
- @thirdweb-dev/auth@4.1.67
## 4.6.7
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "4.6.7",
"version": "4.6.9",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -1,5 +1,9 @@
# @thirdweb-dev/react-native-compat
## 0.7.41
## 0.7.40
## 0.7.39
## 0.7.38
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/react-native-compat",
"description": "Shims for Thirdweb in React Native Projects",
"version": "0.7.39",
"version": "0.7.41",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-native-compat",
"license": "Apache-2.0",
+19
View File
@@ -1,5 +1,24 @@
# @thirdweb-dev/react-native
## 0.7.41
### Patch Changes
- Updated dependencies [[`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc)]:
- @thirdweb-dev/sdk@4.0.70
- @thirdweb-dev/chains@0.1.100
- @thirdweb-dev/react-core@4.6.9
- @thirdweb-dev/wallets@2.5.10
## 0.7.40
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.69
- @thirdweb-dev/react-core@4.6.8
- @thirdweb-dev/wallets@2.5.9
## 0.7.39
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.7.39",
"version": "0.7.41",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+21
View File
@@ -1,5 +1,26 @@
# @thirdweb-dev/react
## 4.6.9
### Patch Changes
- Updated dependencies [[`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc)]:
- @thirdweb-dev/sdk@4.0.70
- @thirdweb-dev/chains@0.1.100
- @thirdweb-dev/react-core@4.6.9
- @thirdweb-dev/wallets@2.5.10
## 4.6.8
### Patch Changes
- [#2679](https://github.com/thirdweb-dev/js/pull/2679) [`560d8ad`](https://github.com/thirdweb-dev/js/commit/560d8adafa011dc48e48e73d7eb6a36170d38cef) Thanks [@ElasticBottle](https://github.com/ElasticBottle)! - Fix In-App wallet country selector styles on windows
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.69
- @thirdweb-dev/react-core@4.6.8
- @thirdweb-dev/wallets@2.5.9
## 4.6.7
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "4.6.7",
"version": "4.6.9",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -12,3 +12,4 @@ export const StyledH2 = /* @__PURE__ */ styled.h2;
export const StyledP = /* @__PURE__ */ styled.p;
export const StyledUl = /* @__PURE__ */ styled.ul;
export const StyledSelect = /* @__PURE__ */ styled.select;
export const StyledOption = /* @__PURE__ */ styled.option;
@@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query";
import React, { useRef } from "react";
import { fontSize, spacing } from "../../../design-system";
import { useCustomTheme } from "../../../design-system/CustomThemeProvider";
import { StyledSelect } from "../../../design-system/elements";
import { StyledOption, StyledSelect } from "../../../design-system/elements";
export function CountrySelector({
countryCode,
@@ -52,12 +52,12 @@ export function CountrySelector({
</option>
{supportedCountriesForSms.map((country) => {
return (
<option
<Option
key={country.countryIsoCode}
value={`${country.countryIsoCode} +${country.phoneNumberCode}`}
>
{country.countryName} +{country.phoneNumberCode}{" "}
</option>
</Option>
);
})}
</Select>
@@ -65,7 +65,20 @@ export function CountrySelector({
);
}
export const Select = /* @__PURE__ */ StyledSelect(() => {
const Option = /* @__PURE__ */ StyledOption(() => {
const theme = useCustomTheme();
return {
color: theme.colors.primaryText,
background: theme.colors.modalBg,
transition: "background 0.3s ease",
"&:hover": {
background: theme.colors.walletSelectorButtonHoverBg,
},
};
});
const Select = /* @__PURE__ */ StyledSelect(() => {
const theme = useCustomTheme();
return {
fontSize: fontSize.sm,
Binary file not shown.
+17
View File
@@ -1,5 +1,22 @@
# @thirdweb-dev/sdk
## 4.0.70
### Patch Changes
- [#2848](https://github.com/thirdweb-dev/js/pull/2848) [`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469) Thanks [@jnsdls](https://github.com/jnsdls)! - add `celo` chains to known `op stack` chains
- Updated dependencies [[`2ae9a13`](https://github.com/thirdweb-dev/js/commit/2ae9a13b01e7a436536b3d412690150f9f960c72), [`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc), [`e8e3368`](https://github.com/thirdweb-dev/js/commit/e8e3368fdef1aa9aaefe6243486395b666b47137), [`aa0b8c4`](https://github.com/thirdweb-dev/js/commit/aa0b8c44650b9d0f45f6dff66ebbceb64cfd7be3)]:
- thirdweb@5.12.0
- @thirdweb-dev/chains@0.1.100
## 4.0.69
### Patch Changes
- Updated dependencies [[`560d8ad`](https://github.com/thirdweb-dev/js/commit/560d8adafa011dc48e48e73d7eb6a36170d38cef), [`d7e6671`](https://github.com/thirdweb-dev/js/commit/d7e6671c0a34cc8a3523f397a45d754617c9fbb0), [`948f155`](https://github.com/thirdweb-dev/js/commit/948f155e7c2406cc5a172a6c5abe18ba8da89e2a), [`3be61dd`](https://github.com/thirdweb-dev/js/commit/3be61ddc52cef168cda0bee13e93a926dedf479a), [`cfff7e8`](https://github.com/thirdweb-dev/js/commit/cfff7e838af1c464c9b5fbb547153eaae41e2c66)]:
- thirdweb@5.11.0
## 4.0.68
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "4.0.68",
"version": "4.0.70",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/sdk",
"license": "Apache-2.0",
@@ -11,6 +11,8 @@ import {
BaseSepoliaTestnet,
Zora,
ZoraSepoliaTestnet,
Celo,
CeloAlfajoresTestnet,
} from "@thirdweb-dev/chains";
type FeeData = {
@@ -134,7 +136,9 @@ function isOpStackChain(chainId: number) {
chainId === Base.chainId ||
chainId === BaseSepoliaTestnet.chainId ||
chainId === Zora.chainId ||
chainId === ZoraSepoliaTestnet.chainId
chainId === ZoraSepoliaTestnet.chainId ||
chainId === Celo.chainId ||
chainId === CeloAlfajoresTestnet.chainId
);
}
Binary file not shown.
@@ -1,5 +1,24 @@
# @thirdweb-dev/unity-js-bridge
## 0.6.19
### Patch Changes
- Updated dependencies [[`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc)]:
- @thirdweb-dev/sdk@4.0.70
- @thirdweb-dev/chains@0.1.100
- @thirdweb-dev/wallets@2.5.10
- @thirdweb-dev/auth@4.1.68
## 0.6.18
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.69
- @thirdweb-dev/wallets@2.5.9
- @thirdweb-dev/auth@4.1.67
## 0.6.17
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/unity-js-bridge",
"version": "0.6.17",
"version": "0.6.19",
"main": "dist/thirdweb-unity-bridge.js",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
"license": "Apache-2.0",
+15
View File
@@ -1,5 +1,20 @@
# @thirdweb-dev/wallets
## 2.5.10
### Patch Changes
- Updated dependencies [[`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469), [`637c510`](https://github.com/thirdweb-dev/js/commit/637c510f59c2504bd29cedbdf4bda694719681dc)]:
- @thirdweb-dev/sdk@4.0.70
- @thirdweb-dev/chains@0.1.100
## 2.5.9
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.69
## 2.5.8
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/wallets",
"version": "2.5.8",
"version": "2.5.10",
"main": "dist/thirdweb-dev-wallets.cjs.js",
"module": "dist/thirdweb-dev-wallets.esm.js",
"browser": {
+141
View File
@@ -1,5 +1,146 @@
# thirdweb
## 5.12.0
### Minor Changes
- [#2841](https://github.com/thirdweb-dev/js/pull/2841) [`2ae9a13`](https://github.com/thirdweb-dev/js/commit/2ae9a13b01e7a436536b3d412690150f9f960c72) Thanks [@kumaryash90](https://github.com/kumaryash90)! - SDK V5 extension for new Airdrop contract.
- [#2846](https://github.com/thirdweb-dev/js/pull/2846) [`e8e3368`](https://github.com/thirdweb-dev/js/commit/e8e3368fdef1aa9aaefe6243486395b666b47137) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Add isERC20 extension
### Patch Changes
- [#2848](https://github.com/thirdweb-dev/js/pull/2848) [`41be954`](https://github.com/thirdweb-dev/js/commit/41be954bd0a92d49767d62a6fa02f1ee0effb469) Thanks [@jnsdls](https://github.com/jnsdls)! - add `celo` chains to known `op stack` chains
- [#2850](https://github.com/thirdweb-dev/js/pull/2850) [`aa0b8c4`](https://github.com/thirdweb-dev/js/commit/aa0b8c44650b9d0f45f6dff66ebbceb64cfd7be3) Thanks [@MananTank](https://github.com/MananTank)! - Fix "All wallets" UI in Connect
- Remove duplicated entry for "inApp"
- Remove wallets specified by developer
## 5.11.0
### Minor Changes
- [#2679](https://github.com/thirdweb-dev/js/pull/2679) [`560d8ad`](https://github.com/thirdweb-dev/js/commit/560d8adafa011dc48e48e73d7eb6a36170d38cef) Thanks [@ElasticBottle](https://github.com/ElasticBottle)! - Add support for connecting in-app wallet using phone number
## Usage in TypeScript
```ts
import { createThirdwebClient, createWallet } from "thirdweb";
import { preAuthenticate } from "thirdweb/wallets/in-app";
const client = createThirdwebClient({ clientId: "..." });
const phoneNumber = '+123456789';
// Send OTP to given phone number
async function sendOTP() {
await preAuthenticate({
strategy: "phone",
phoneNumber,
client,
});
}
async function connect() {
// create a in-app wallet instance
const wallet = createWallet('inApp');
// if the OTP is correct, the wallet will be connected else an error will be thrown
const account = await wallet.connect({
client,
strategy: "phone";
phoneNumber,
verificationCode: '...' // Pass the OTP entered by the user
});
console.log('connected to', account);
}
```
## Usage in React
```tsx
import { createThirdwebClient } from "thirdweb";
import { preAuthenticate } from "thirdweb/wallets/in-app";
import { useConnect } from "thirdweb/react";
const client = createThirdwebClient({ clientId: "..." });
function Component() {
const { connect } = useConnect();
const [phoneNumber, setPhoneNumber] = useState(''); // get phone number from user
const [otp, setOtp] = useState(''); // get OTP from user
// Send OTP to given phone number
async function sendOTP() {
await preAuthenticate({
strategy: "phone",
phoneNumber,
client,
});
}
async function connect() {
// create a in-app wallet instance
const wallet = createWallet('inApp');
// if the OTP is correct, the wallet will be connected else an error will be thrown
await wallet.connect({
client,
strategy: "phone";
phoneNumber,
verificationCode: otp
});
// set the wallet as active
connect(wallet)
}
// render UI to get OTP and phone number from user
return <div> ... </div>
}
```
- [#2818](https://github.com/thirdweb-dev/js/pull/2818) [`948f155`](https://github.com/thirdweb-dev/js/commit/948f155e7c2406cc5a172a6c5abe18ba8da89e2a) Thanks [@jnsdls](https://github.com/jnsdls)! - **Gasless transactions in Typescript**
```ts
import { sendTransaction } from "thirdweb";
const result = sendTransaction({
transaction,
account,
gasless: {
provider: "engine",
relayerUrl: "https://...",
relayerForwarderAddress: "0x...",
},
});
```
**Gasless transactions in React**
```jsx
import { useSendTransaction } from "thirdweb/react";
const { mutate } = useSendTransaction({
gasless: {
provider: "engine",
relayerUrl: "https://...",
relayerForwarderAddress: "0x...",
},
});
// Call mutate with the transaction object
mutate(transaction);
```
### Patch Changes
- [#2842](https://github.com/thirdweb-dev/js/pull/2842) [`d7e6671`](https://github.com/thirdweb-dev/js/commit/d7e6671c0a34cc8a3523f397a45d754617c9fbb0) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - fix: handle signature minting with price and currency
- [#2839](https://github.com/thirdweb-dev/js/pull/2839) [`3be61dd`](https://github.com/thirdweb-dev/js/commit/3be61ddc52cef168cda0bee13e93a926dedf479a) Thanks [@MananTank](https://github.com/MananTank)! - Enable Buy Modal by default with useSendTransaction hook
- [#2768](https://github.com/thirdweb-dev/js/pull/2768) [`cfff7e8`](https://github.com/thirdweb-dev/js/commit/cfff7e838af1c464c9b5fbb547153eaae41e2c66) Thanks [@MananTank](https://github.com/MananTank)! - Fix custom chain not being used
## 5.10.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "thirdweb",
"version": "5.10.1",
"version": "5.12.0",
"repository": {
"type": "git",
"url": "git+https://github.com/thirdweb-dev/js.git#main"
@@ -0,0 +1,408 @@
[
"function tokenConditionId(address tokenAddress) view returns (uint256)",
"function tokenMerkleRoot(address tokenAddress) view returns (bytes32)",
{ "type": "constructor", "inputs": [], "stateMutability": "nonpayable" },
{
"type": "function",
"name": "airdropERC1155",
"inputs": [
{ "name": "_tokenAddress", "type": "address", "internalType": "address" },
{
"name": "_contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC1155[]",
"components": [
{ "name": "recipient", "type": "address", "internalType": "address" },
{ "name": "tokenId", "type": "uint256", "internalType": "uint256" },
{ "name": "amount", "type": "uint256", "internalType": "uint256" }
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "airdropERC1155WithSignature",
"inputs": [
{
"name": "req",
"type": "tuple",
"internalType": "struct Airdrop.AirdropRequestERC1155",
"components": [
{ "name": "uid", "type": "bytes32", "internalType": "bytes32" },
{
"name": "tokenAddress",
"type": "address",
"internalType": "address"
},
{
"name": "expirationTimestamp",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC1155[]",
"components": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "tokenId",
"type": "uint256",
"internalType": "uint256"
},
{ "name": "amount", "type": "uint256", "internalType": "uint256" }
]
}
]
},
{ "name": "signature", "type": "bytes", "internalType": "bytes" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "airdropERC20",
"inputs": [
{ "name": "_tokenAddress", "type": "address", "internalType": "address" },
{
"name": "_contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC20[]",
"components": [
{ "name": "recipient", "type": "address", "internalType": "address" },
{ "name": "amount", "type": "uint256", "internalType": "uint256" }
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "airdropERC20WithSignature",
"inputs": [
{
"name": "req",
"type": "tuple",
"internalType": "struct Airdrop.AirdropRequestERC20",
"components": [
{ "name": "uid", "type": "bytes32", "internalType": "bytes32" },
{
"name": "tokenAddress",
"type": "address",
"internalType": "address"
},
{
"name": "expirationTimestamp",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC20[]",
"components": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{ "name": "amount", "type": "uint256", "internalType": "uint256" }
]
}
]
},
{ "name": "signature", "type": "bytes", "internalType": "bytes" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "airdropERC721",
"inputs": [
{ "name": "_tokenAddress", "type": "address", "internalType": "address" },
{
"name": "_contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC721[]",
"components": [
{ "name": "recipient", "type": "address", "internalType": "address" },
{ "name": "tokenId", "type": "uint256", "internalType": "uint256" }
]
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "airdropERC721WithSignature",
"inputs": [
{
"name": "req",
"type": "tuple",
"internalType": "struct Airdrop.AirdropRequestERC721",
"components": [
{ "name": "uid", "type": "bytes32", "internalType": "bytes32" },
{
"name": "tokenAddress",
"type": "address",
"internalType": "address"
},
{
"name": "expirationTimestamp",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC721[]",
"components": [
{
"name": "recipient",
"type": "address",
"internalType": "address"
},
{
"name": "tokenId",
"type": "uint256",
"internalType": "uint256"
}
]
}
]
},
{ "name": "signature", "type": "bytes", "internalType": "bytes" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "airdropNativeToken",
"inputs": [
{
"name": "_contents",
"type": "tuple[]",
"internalType": "struct Airdrop.AirdropContentERC20[]",
"components": [
{ "name": "recipient", "type": "address", "internalType": "address" },
{ "name": "amount", "type": "uint256", "internalType": "uint256" }
]
}
],
"outputs": [],
"stateMutability": "payable"
},
{
"type": "function",
"name": "claimERC1155",
"inputs": [
{ "name": "_token", "type": "address", "internalType": "address" },
{ "name": "_receiver", "type": "address", "internalType": "address" },
{ "name": "_tokenId", "type": "uint256", "internalType": "uint256" },
{ "name": "_quantity", "type": "uint256", "internalType": "uint256" },
{ "name": "_proofs", "type": "bytes32[]", "internalType": "bytes32[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "claimERC20",
"inputs": [
{ "name": "_token", "type": "address", "internalType": "address" },
{ "name": "_receiver", "type": "address", "internalType": "address" },
{ "name": "_quantity", "type": "uint256", "internalType": "uint256" },
{ "name": "_proofs", "type": "bytes32[]", "internalType": "bytes32[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "claimERC721",
"inputs": [
{ "name": "_token", "type": "address", "internalType": "address" },
{ "name": "_receiver", "type": "address", "internalType": "address" },
{ "name": "_tokenId", "type": "uint256", "internalType": "uint256" },
{ "name": "_proofs", "type": "bytes32[]", "internalType": "bytes32[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "eip712Domain",
"inputs": [],
"outputs": [
{ "name": "fields", "type": "bytes1", "internalType": "bytes1" },
{ "name": "name", "type": "string", "internalType": "string" },
{ "name": "version", "type": "string", "internalType": "string" },
{ "name": "chainId", "type": "uint256", "internalType": "uint256" },
{
"name": "verifyingContract",
"type": "address",
"internalType": "address"
},
{ "name": "salt", "type": "bytes32", "internalType": "bytes32" },
{ "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "initialize",
"inputs": [
{ "name": "_defaultAdmin", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "isClaimed",
"inputs": [
{ "name": "_receiver", "type": "address", "internalType": "address" },
{ "name": "_token", "type": "address", "internalType": "address" },
{ "name": "_tokenId", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "owner",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "setMerkleRoot",
"inputs": [
{ "name": "_token", "type": "address", "internalType": "address" },
{
"name": "_tokenMerkleRoot",
"type": "bytes32",
"internalType": "bytes32"
},
{ "name": "_resetClaimStatus", "type": "bool", "internalType": "bool" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setOwner",
"inputs": [
{ "name": "_newOwner", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "event",
"name": "Airdrop",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "AirdropClaimed",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "receiver",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "AirdropWithSignature",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Initialized",
"inputs": [
{
"name": "version",
"type": "uint8",
"indexed": false,
"internalType": "uint8"
}
],
"anonymous": false
},
{
"type": "event",
"name": "OwnerUpdated",
"inputs": [
{
"name": "prevOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{ "type": "error", "name": "AirdropAlreadyClaimed", "inputs": [] },
{ "type": "error", "name": "AirdropInvalidProof", "inputs": [] },
{ "type": "error", "name": "AirdropNoMerkleRoot", "inputs": [] },
{ "type": "error", "name": "AirdropRequestAlreadyProcessed", "inputs": [] },
{
"type": "error",
"name": "AirdropRequestExpired",
"inputs": [
{
"name": "expirationTimestamp",
"type": "uint256",
"internalType": "uint256"
}
]
},
{ "type": "error", "name": "AirdropRequestInvalidSigner", "inputs": [] },
{ "type": "error", "name": "AirdropValueMismatch", "inputs": [] },
{ "type": "error", "name": "OwnableUnauthorized", "inputs": [] }
]
@@ -15,6 +15,8 @@ const opChains = [
zoraSepolia.id,
34443, // mode
919, // mode testnet
42220, // celo
44787, // celo testnet
];
/**
@@ -18,9 +18,11 @@ export async function getOrDeployInfraForPublishedContract(
args: ClientAndChainAndAccount & {
contractId: string;
constructorParams: unknown[];
publisher?: string;
},
) {
const { chain, client, account, contractId, constructorParams } = args;
const { chain, client, account, contractId, constructorParams, publisher } =
args;
let [cloneFactoryContract, implementationContract] = await Promise.all([
getDeployedCloneFactoryContract({
chain,
@@ -31,6 +33,7 @@ export async function getOrDeployInfraForPublishedContract(
client,
contractId,
constructorParams,
publisher,
}),
]);
@@ -47,6 +50,7 @@ export async function getOrDeployInfraForPublishedContract(
account,
contractId,
constructorParams,
publisher,
});
}
return { cloneFactoryContract, implementationContract };
@@ -1,4 +1,5 @@
// read
export { isERC20 } from "../../extensions/erc20/read/isERC20.js";
export {
getBalance,
type GetBalanceParams,
@@ -0,0 +1,24 @@
import { prepareEvent } from "../../../../../event/prepare-event.js";
/**
* Creates an event object for the Airdrop event.
* @returns The prepared event object.
* @extension AIRDROP
* @example
* ```ts
* import { getContractEvents } from "thirdweb";
* import { airdropEvent } from "thirdweb/extensions/airdrop";
*
* const events = await getContractEvents({
* contract,
* events: [
* airdropEvent()
* ],
* });
* ```
*/
export function airdropEvent() {
return prepareEvent({
signature: "event Airdrop(address token)",
});
}
@@ -0,0 +1,24 @@
import { prepareEvent } from "../../../../../event/prepare-event.js";
/**
* Creates an event object for the AirdropClaimed event.
* @returns The prepared event object.
* @extension AIRDROP
* @example
* ```ts
* import { getContractEvents } from "thirdweb";
* import { airdropClaimedEvent } from "thirdweb/extensions/airdrop";
*
* const events = await getContractEvents({
* contract,
* events: [
* airdropClaimedEvent()
* ],
* });
* ```
*/
export function airdropClaimedEvent() {
return prepareEvent({
signature: "event AirdropClaimed(address token, address receiver)",
});
}
@@ -0,0 +1,24 @@
import { prepareEvent } from "../../../../../event/prepare-event.js";
/**
* Creates an event object for the AirdropWithSignature event.
* @returns The prepared event object.
* @extension AIRDROP
* @example
* ```ts
* import { getContractEvents } from "thirdweb";
* import { airdropWithSignatureEvent } from "thirdweb/extensions/airdrop";
*
* const events = await getContractEvents({
* contract,
* events: [
* airdropWithSignatureEvent()
* ],
* });
* ```
*/
export function airdropWithSignatureEvent() {
return prepareEvent({
signature: "event AirdropWithSignature(address token)",
});
}
@@ -0,0 +1,24 @@
import { prepareEvent } from "../../../../../event/prepare-event.js";
/**
* Creates an event object for the ContractURIUpdated event.
* @returns The prepared event object.
* @extension AIRDROP
* @example
* ```ts
* import { getContractEvents } from "thirdweb";
* import { contractURIUpdatedEvent } from "thirdweb/extensions/airdrop";
*
* const events = await getContractEvents({
* contract,
* events: [
* contractURIUpdatedEvent()
* ],
* });
* ```
*/
export function contractURIUpdatedEvent() {
return prepareEvent({
signature: "event ContractURIUpdated(string prevURI, string newURI)",
});
}
@@ -0,0 +1,24 @@
import { prepareEvent } from "../../../../../event/prepare-event.js";
/**
* Creates an event object for the Initialized event.
* @returns The prepared event object.
* @extension AIRDROP
* @example
* ```ts
* import { getContractEvents } from "thirdweb";
* import { initializedEvent } from "thirdweb/extensions/airdrop";
*
* const events = await getContractEvents({
* contract,
* events: [
* initializedEvent()
* ],
* });
* ```
*/
export function initializedEvent() {
return prepareEvent({
signature: "event Initialized(uint8 version)",
});
}
@@ -0,0 +1,49 @@
import { prepareEvent } from "../../../../../event/prepare-event.js";
import type { AbiParameterToPrimitiveType } from "abitype";
/**
* Represents the filters for the "OwnerUpdated" event.
*/
export type OwnerUpdatedEventFilters = Partial<{
prevOwner: AbiParameterToPrimitiveType<{
name: "prevOwner";
type: "address";
indexed: true;
internalType: "address";
}>;
newOwner: AbiParameterToPrimitiveType<{
name: "newOwner";
type: "address";
indexed: true;
internalType: "address";
}>;
}>;
/**
* Creates an event object for the OwnerUpdated event.
* @param filters - Optional filters to apply to the event.
* @returns The prepared event object.
* @extension AIRDROP
* @example
* ```ts
* import { getContractEvents } from "thirdweb";
* import { ownerUpdatedEvent } from "thirdweb/extensions/airdrop";
*
* const events = await getContractEvents({
* contract,
* events: [
* ownerUpdatedEvent({
* prevOwner: ...,
* newOwner: ...,
* })
* ],
* });
* ```
*/
export function ownerUpdatedEvent(filters: OwnerUpdatedEventFilters = {}) {
return prepareEvent({
signature:
"event OwnerUpdated(address indexed prevOwner, address indexed newOwner)",
filters,
});
}
@@ -0,0 +1,70 @@
import { readContract } from "../../../../../transaction/read-contract.js";
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
import { decodeAbiParameters } from "viem";
import type { Hex } from "../../../../../utils/encoding/hex.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
export const FN_SELECTOR = "0xe8a3d485" as const;
const FN_INPUTS = [] as const;
const FN_OUTPUTS = [
{
type: "string",
},
] as const;
/**
* Checks if the `contractURI` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `contractURI` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isContractURISupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isContractURISupported(contract);
* ```
*/
export async function isContractURISupported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Decodes the result of the contractURI function call.
* @param result - The hexadecimal result to decode.
* @returns The decoded result as per the FN_OUTPUTS definition.
* @extension AIRDROP
* @example
* ```ts
* import { decodeContractURIResult } from "thirdweb/extensions/airdrop";
* const result = decodeContractURIResult("...");
* ```
*/
export function decodeContractURIResult(result: Hex) {
return decodeAbiParameters(FN_OUTPUTS, result)[0];
}
/**
* Calls the "contractURI" function on the contract.
* @param options - The options for the contractURI function.
* @returns The parsed result of the function call.
* @extension AIRDROP
* @example
* ```ts
* import { contractURI } from "thirdweb/extensions/airdrop";
*
* const result = await contractURI();
*
* ```
*/
export async function contractURI(options: BaseTransactionOptions) {
return readContract({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: [],
});
}
@@ -0,0 +1,102 @@
import { readContract } from "../../../../../transaction/read-contract.js";
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
import { decodeAbiParameters } from "viem";
import type { Hex } from "../../../../../utils/encoding/hex.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
export const FN_SELECTOR = "0x84b0196e" as const;
const FN_INPUTS = [] as const;
const FN_OUTPUTS = [
{
name: "fields",
type: "bytes1",
internalType: "bytes1",
},
{
name: "name",
type: "string",
internalType: "string",
},
{
name: "version",
type: "string",
internalType: "string",
},
{
name: "chainId",
type: "uint256",
internalType: "uint256",
},
{
name: "verifyingContract",
type: "address",
internalType: "address",
},
{
name: "salt",
type: "bytes32",
internalType: "bytes32",
},
{
name: "extensions",
type: "uint256[]",
internalType: "uint256[]",
},
] as const;
/**
* Checks if the `eip712Domain` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `eip712Domain` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isEip712DomainSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isEip712DomainSupported(contract);
* ```
*/
export async function isEip712DomainSupported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Decodes the result of the eip712Domain function call.
* @param result - The hexadecimal result to decode.
* @returns The decoded result as per the FN_OUTPUTS definition.
* @extension AIRDROP
* @example
* ```ts
* import { decodeEip712DomainResult } from "thirdweb/extensions/airdrop";
* const result = decodeEip712DomainResult("...");
* ```
*/
export function decodeEip712DomainResult(result: Hex) {
return decodeAbiParameters(FN_OUTPUTS, result);
}
/**
* Calls the "eip712Domain" function on the contract.
* @param options - The options for the eip712Domain function.
* @returns The parsed result of the function call.
* @extension AIRDROP
* @example
* ```ts
* import { eip712Domain } from "thirdweb/extensions/airdrop";
*
* const result = await eip712Domain();
*
* ```
*/
export async function eip712Domain(options: BaseTransactionOptions) {
return readContract({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: [],
});
}
@@ -0,0 +1,163 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import { readContract } from "../../../../../transaction/read-contract.js";
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { decodeAbiParameters } from "viem";
import type { Hex } from "../../../../../utils/encoding/hex.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "isClaimed" function.
*/
export type IsClaimedParams = {
receiver: AbiParameterToPrimitiveType<{
name: "_receiver";
type: "address";
internalType: "address";
}>;
token: AbiParameterToPrimitiveType<{
name: "_token";
type: "address";
internalType: "address";
}>;
tokenId: AbiParameterToPrimitiveType<{
name: "_tokenId";
type: "uint256";
internalType: "uint256";
}>;
};
export const FN_SELECTOR = "0xd12acf73" as const;
const FN_INPUTS = [
{
name: "_receiver",
type: "address",
internalType: "address",
},
{
name: "_token",
type: "address",
internalType: "address",
},
{
name: "_tokenId",
type: "uint256",
internalType: "uint256",
},
] as const;
const FN_OUTPUTS = [
{
name: "",
type: "bool",
internalType: "bool",
},
] as const;
/**
* Checks if the `isClaimed` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `isClaimed` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isIsClaimedSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isIsClaimedSupported(contract);
* ```
*/
export async function isIsClaimedSupported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "isClaimed" function.
* @param options - The options for the isClaimed function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeIsClaimedParams } "thirdweb/extensions/airdrop";
* const result = encodeIsClaimedParams({
* receiver: ...,
* token: ...,
* tokenId: ...,
* });
* ```
*/
export function encodeIsClaimedParams(options: IsClaimedParams) {
return encodeAbiParameters(FN_INPUTS, [
options.receiver,
options.token,
options.tokenId,
]);
}
/**
* Encodes the "isClaimed" function into a Hex string with its parameters.
* @param options - The options for the isClaimed function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeIsClaimed } "thirdweb/extensions/airdrop";
* const result = encodeIsClaimed({
* receiver: ...,
* token: ...,
* tokenId: ...,
* });
* ```
*/
export function encodeIsClaimed(options: IsClaimedParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeIsClaimedParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Decodes the result of the isClaimed function call.
* @param result - The hexadecimal result to decode.
* @returns The decoded result as per the FN_OUTPUTS definition.
* @extension AIRDROP
* @example
* ```ts
* import { decodeIsClaimedResult } from "thirdweb/extensions/airdrop";
* const result = decodeIsClaimedResult("...");
* ```
*/
export function decodeIsClaimedResult(result: Hex) {
return decodeAbiParameters(FN_OUTPUTS, result)[0];
}
/**
* Calls the "isClaimed" function on the contract.
* @param options - The options for the isClaimed function.
* @returns The parsed result of the function call.
* @extension AIRDROP
* @example
* ```ts
* import { isClaimed } from "thirdweb/extensions/airdrop";
*
* const result = await isClaimed({
* receiver: ...,
* token: ...,
* tokenId: ...,
* });
*
* ```
*/
export async function isClaimed(
options: BaseTransactionOptions<IsClaimedParams>,
) {
return readContract({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: [options.receiver, options.token, options.tokenId],
});
}
@@ -0,0 +1,72 @@
import { readContract } from "../../../../../transaction/read-contract.js";
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
import { decodeAbiParameters } from "viem";
import type { Hex } from "../../../../../utils/encoding/hex.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
export const FN_SELECTOR = "0x8da5cb5b" as const;
const FN_INPUTS = [] as const;
const FN_OUTPUTS = [
{
name: "",
type: "address",
internalType: "address",
},
] as const;
/**
* Checks if the `owner` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `owner` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isOwnerSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isOwnerSupported(contract);
* ```
*/
export async function isOwnerSupported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Decodes the result of the owner function call.
* @param result - The hexadecimal result to decode.
* @returns The decoded result as per the FN_OUTPUTS definition.
* @extension AIRDROP
* @example
* ```ts
* import { decodeOwnerResult } from "thirdweb/extensions/airdrop";
* const result = decodeOwnerResult("...");
* ```
*/
export function decodeOwnerResult(result: Hex) {
return decodeAbiParameters(FN_OUTPUTS, result)[0];
}
/**
* Calls the "owner" function on the contract.
* @param options - The options for the owner function.
* @returns The parsed result of the function call.
* @extension AIRDROP
* @example
* ```ts
* import { owner } from "thirdweb/extensions/airdrop";
*
* const result = await owner();
*
* ```
*/
export async function owner(options: BaseTransactionOptions) {
return readContract({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: [],
});
}
@@ -0,0 +1,131 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import { readContract } from "../../../../../transaction/read-contract.js";
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { decodeAbiParameters } from "viem";
import type { Hex } from "../../../../../utils/encoding/hex.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "tokenConditionId" function.
*/
export type TokenConditionIdParams = {
tokenAddress: AbiParameterToPrimitiveType<{
type: "address";
name: "tokenAddress";
}>;
};
export const FN_SELECTOR = "0x3dc28d49" as const;
const FN_INPUTS = [
{
type: "address",
name: "tokenAddress",
},
] as const;
const FN_OUTPUTS = [
{
type: "uint256",
},
] as const;
/**
* Checks if the `tokenConditionId` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `tokenConditionId` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isTokenConditionIdSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isTokenConditionIdSupported(contract);
* ```
*/
export async function isTokenConditionIdSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "tokenConditionId" function.
* @param options - The options for the tokenConditionId function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeTokenConditionIdParams } "thirdweb/extensions/airdrop";
* const result = encodeTokenConditionIdParams({
* tokenAddress: ...,
* });
* ```
*/
export function encodeTokenConditionIdParams(options: TokenConditionIdParams) {
return encodeAbiParameters(FN_INPUTS, [options.tokenAddress]);
}
/**
* Encodes the "tokenConditionId" function into a Hex string with its parameters.
* @param options - The options for the tokenConditionId function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeTokenConditionId } "thirdweb/extensions/airdrop";
* const result = encodeTokenConditionId({
* tokenAddress: ...,
* });
* ```
*/
export function encodeTokenConditionId(options: TokenConditionIdParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeTokenConditionIdParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Decodes the result of the tokenConditionId function call.
* @param result - The hexadecimal result to decode.
* @returns The decoded result as per the FN_OUTPUTS definition.
* @extension AIRDROP
* @example
* ```ts
* import { decodeTokenConditionIdResult } from "thirdweb/extensions/airdrop";
* const result = decodeTokenConditionIdResult("...");
* ```
*/
export function decodeTokenConditionIdResult(result: Hex) {
return decodeAbiParameters(FN_OUTPUTS, result)[0];
}
/**
* Calls the "tokenConditionId" function on the contract.
* @param options - The options for the tokenConditionId function.
* @returns The parsed result of the function call.
* @extension AIRDROP
* @example
* ```ts
* import { tokenConditionId } from "thirdweb/extensions/airdrop";
*
* const result = await tokenConditionId({
* tokenAddress: ...,
* });
*
* ```
*/
export async function tokenConditionId(
options: BaseTransactionOptions<TokenConditionIdParams>,
) {
return readContract({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: [options.tokenAddress],
});
}
@@ -0,0 +1,131 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import { readContract } from "../../../../../transaction/read-contract.js";
import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { decodeAbiParameters } from "viem";
import type { Hex } from "../../../../../utils/encoding/hex.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "tokenMerkleRoot" function.
*/
export type TokenMerkleRootParams = {
tokenAddress: AbiParameterToPrimitiveType<{
type: "address";
name: "tokenAddress";
}>;
};
export const FN_SELECTOR = "0x95f5c120" as const;
const FN_INPUTS = [
{
type: "address",
name: "tokenAddress",
},
] as const;
const FN_OUTPUTS = [
{
type: "bytes32",
},
] as const;
/**
* Checks if the `tokenMerkleRoot` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `tokenMerkleRoot` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isTokenMerkleRootSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isTokenMerkleRootSupported(contract);
* ```
*/
export async function isTokenMerkleRootSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "tokenMerkleRoot" function.
* @param options - The options for the tokenMerkleRoot function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeTokenMerkleRootParams } "thirdweb/extensions/airdrop";
* const result = encodeTokenMerkleRootParams({
* tokenAddress: ...,
* });
* ```
*/
export function encodeTokenMerkleRootParams(options: TokenMerkleRootParams) {
return encodeAbiParameters(FN_INPUTS, [options.tokenAddress]);
}
/**
* Encodes the "tokenMerkleRoot" function into a Hex string with its parameters.
* @param options - The options for the tokenMerkleRoot function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeTokenMerkleRoot } "thirdweb/extensions/airdrop";
* const result = encodeTokenMerkleRoot({
* tokenAddress: ...,
* });
* ```
*/
export function encodeTokenMerkleRoot(options: TokenMerkleRootParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeTokenMerkleRootParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Decodes the result of the tokenMerkleRoot function call.
* @param result - The hexadecimal result to decode.
* @returns The decoded result as per the FN_OUTPUTS definition.
* @extension AIRDROP
* @example
* ```ts
* import { decodeTokenMerkleRootResult } from "thirdweb/extensions/airdrop";
* const result = decodeTokenMerkleRootResult("...");
* ```
*/
export function decodeTokenMerkleRootResult(result: Hex) {
return decodeAbiParameters(FN_OUTPUTS, result)[0];
}
/**
* Calls the "tokenMerkleRoot" function on the contract.
* @param options - The options for the tokenMerkleRoot function.
* @returns The parsed result of the function call.
* @extension AIRDROP
* @example
* ```ts
* import { tokenMerkleRoot } from "thirdweb/extensions/airdrop";
*
* const result = await tokenMerkleRoot({
* tokenAddress: ...,
* });
*
* ```
*/
export async function tokenMerkleRoot(
options: BaseTransactionOptions<TokenMerkleRootParams>,
) {
return readContract({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: [options.tokenAddress],
});
}
@@ -0,0 +1,171 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropERC1155" function.
*/
export type AirdropERC1155Params = WithOverrides<{
tokenAddress: AbiParameterToPrimitiveType<{
name: "_tokenAddress";
type: "address";
internalType: "address";
}>;
contents: AbiParameterToPrimitiveType<{
name: "_contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC1155[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "tokenId"; type: "uint256"; internalType: "uint256" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
}>;
}>;
export const FN_SELECTOR = "0x2d89e38b" as const;
const FN_INPUTS = [
{
name: "_tokenAddress",
type: "address",
internalType: "address",
},
{
name: "_contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC1155[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "tokenId",
type: "uint256",
internalType: "uint256",
},
{
name: "amount",
type: "uint256",
internalType: "uint256",
},
],
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropERC1155` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropERC1155` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropERC1155Supported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropERC1155Supported(contract);
* ```
*/
export async function isAirdropERC1155Supported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropERC1155" function.
* @param options - The options for the airdropERC1155 function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC1155Params } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC1155Params({
* tokenAddress: ...,
* contents: ...,
* });
* ```
*/
export function encodeAirdropERC1155Params(options: AirdropERC1155Params) {
return encodeAbiParameters(FN_INPUTS, [
options.tokenAddress,
options.contents,
]);
}
/**
* Encodes the "airdropERC1155" function into a Hex string with its parameters.
* @param options - The options for the airdropERC1155 function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC1155 } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC1155({
* tokenAddress: ...,
* contents: ...,
* });
* ```
*/
export function encodeAirdropERC1155(options: AirdropERC1155Params) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropERC1155Params(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropERC1155" function on the contract.
* @param options - The options for the "airdropERC1155" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropERC1155 } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropERC1155({
* contract,
* tokenAddress: ...,
* contents: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropERC1155(
options: BaseTransactionOptions<
| AirdropERC1155Params
| {
asyncParams: () => Promise<AirdropERC1155Params>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.tokenAddress, resolvedOptions.contents] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,204 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropERC1155WithSignature" function.
*/
export type AirdropERC1155WithSignatureParams = WithOverrides<{
req: AbiParameterToPrimitiveType<{
name: "req";
type: "tuple";
internalType: "struct Airdrop.AirdropRequestERC1155";
components: [
{ name: "uid"; type: "bytes32"; internalType: "bytes32" },
{ name: "tokenAddress"; type: "address"; internalType: "address" },
{ name: "expirationTimestamp"; type: "uint256"; internalType: "uint256" },
{
name: "contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC1155[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "tokenId"; type: "uint256"; internalType: "uint256" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
},
];
}>;
signature: AbiParameterToPrimitiveType<{
name: "signature";
type: "bytes";
internalType: "bytes";
}>;
}>;
export const FN_SELECTOR = "0xd0d4afd6" as const;
const FN_INPUTS = [
{
name: "req",
type: "tuple",
internalType: "struct Airdrop.AirdropRequestERC1155",
components: [
{
name: "uid",
type: "bytes32",
internalType: "bytes32",
},
{
name: "tokenAddress",
type: "address",
internalType: "address",
},
{
name: "expirationTimestamp",
type: "uint256",
internalType: "uint256",
},
{
name: "contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC1155[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "tokenId",
type: "uint256",
internalType: "uint256",
},
{
name: "amount",
type: "uint256",
internalType: "uint256",
},
],
},
],
},
{
name: "signature",
type: "bytes",
internalType: "bytes",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropERC1155WithSignature` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropERC1155WithSignature` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropERC1155WithSignatureSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropERC1155WithSignatureSupported(contract);
* ```
*/
export async function isAirdropERC1155WithSignatureSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropERC1155WithSignature" function.
* @param options - The options for the airdropERC1155WithSignature function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC1155WithSignatureParams } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC1155WithSignatureParams({
* req: ...,
* signature: ...,
* });
* ```
*/
export function encodeAirdropERC1155WithSignatureParams(
options: AirdropERC1155WithSignatureParams,
) {
return encodeAbiParameters(FN_INPUTS, [options.req, options.signature]);
}
/**
* Encodes the "airdropERC1155WithSignature" function into a Hex string with its parameters.
* @param options - The options for the airdropERC1155WithSignature function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC1155WithSignature } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC1155WithSignature({
* req: ...,
* signature: ...,
* });
* ```
*/
export function encodeAirdropERC1155WithSignature(
options: AirdropERC1155WithSignatureParams,
) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropERC1155WithSignatureParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropERC1155WithSignature" function on the contract.
* @param options - The options for the "airdropERC1155WithSignature" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropERC1155WithSignature } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropERC1155WithSignature({
* contract,
* req: ...,
* signature: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropERC1155WithSignature(
options: BaseTransactionOptions<
| AirdropERC1155WithSignatureParams
| {
asyncParams: () => Promise<AirdropERC1155WithSignatureParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.req, resolvedOptions.signature] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,163 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropERC20" function.
*/
export type AirdropERC20Params = WithOverrides<{
tokenAddress: AbiParameterToPrimitiveType<{
name: "_tokenAddress";
type: "address";
internalType: "address";
}>;
contents: AbiParameterToPrimitiveType<{
name: "_contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC20[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
}>;
}>;
export const FN_SELECTOR = "0x56b0b449" as const;
const FN_INPUTS = [
{
name: "_tokenAddress",
type: "address",
internalType: "address",
},
{
name: "_contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC20[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "amount",
type: "uint256",
internalType: "uint256",
},
],
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropERC20` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropERC20` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropERC20Supported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropERC20Supported(contract);
* ```
*/
export async function isAirdropERC20Supported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropERC20" function.
* @param options - The options for the airdropERC20 function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC20Params } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC20Params({
* tokenAddress: ...,
* contents: ...,
* });
* ```
*/
export function encodeAirdropERC20Params(options: AirdropERC20Params) {
return encodeAbiParameters(FN_INPUTS, [
options.tokenAddress,
options.contents,
]);
}
/**
* Encodes the "airdropERC20" function into a Hex string with its parameters.
* @param options - The options for the airdropERC20 function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC20 } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC20({
* tokenAddress: ...,
* contents: ...,
* });
* ```
*/
export function encodeAirdropERC20(options: AirdropERC20Params) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropERC20Params(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropERC20" function on the contract.
* @param options - The options for the "airdropERC20" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropERC20 } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropERC20({
* contract,
* tokenAddress: ...,
* contents: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropERC20(
options: BaseTransactionOptions<
| AirdropERC20Params
| {
asyncParams: () => Promise<AirdropERC20Params>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.tokenAddress, resolvedOptions.contents] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,198 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropERC20WithSignature" function.
*/
export type AirdropERC20WithSignatureParams = WithOverrides<{
req: AbiParameterToPrimitiveType<{
name: "req";
type: "tuple";
internalType: "struct Airdrop.AirdropRequestERC20";
components: [
{ name: "uid"; type: "bytes32"; internalType: "bytes32" },
{ name: "tokenAddress"; type: "address"; internalType: "address" },
{ name: "expirationTimestamp"; type: "uint256"; internalType: "uint256" },
{
name: "contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC20[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
},
];
}>;
signature: AbiParameterToPrimitiveType<{
name: "signature";
type: "bytes";
internalType: "bytes";
}>;
}>;
export const FN_SELECTOR = "0xaaba07f6" as const;
const FN_INPUTS = [
{
name: "req",
type: "tuple",
internalType: "struct Airdrop.AirdropRequestERC20",
components: [
{
name: "uid",
type: "bytes32",
internalType: "bytes32",
},
{
name: "tokenAddress",
type: "address",
internalType: "address",
},
{
name: "expirationTimestamp",
type: "uint256",
internalType: "uint256",
},
{
name: "contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC20[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "amount",
type: "uint256",
internalType: "uint256",
},
],
},
],
},
{
name: "signature",
type: "bytes",
internalType: "bytes",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropERC20WithSignature` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropERC20WithSignature` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropERC20WithSignatureSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropERC20WithSignatureSupported(contract);
* ```
*/
export async function isAirdropERC20WithSignatureSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropERC20WithSignature" function.
* @param options - The options for the airdropERC20WithSignature function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC20WithSignatureParams } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC20WithSignatureParams({
* req: ...,
* signature: ...,
* });
* ```
*/
export function encodeAirdropERC20WithSignatureParams(
options: AirdropERC20WithSignatureParams,
) {
return encodeAbiParameters(FN_INPUTS, [options.req, options.signature]);
}
/**
* Encodes the "airdropERC20WithSignature" function into a Hex string with its parameters.
* @param options - The options for the airdropERC20WithSignature function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC20WithSignature } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC20WithSignature({
* req: ...,
* signature: ...,
* });
* ```
*/
export function encodeAirdropERC20WithSignature(
options: AirdropERC20WithSignatureParams,
) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropERC20WithSignatureParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropERC20WithSignature" function on the contract.
* @param options - The options for the "airdropERC20WithSignature" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropERC20WithSignature } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropERC20WithSignature({
* contract,
* req: ...,
* signature: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropERC20WithSignature(
options: BaseTransactionOptions<
| AirdropERC20WithSignatureParams
| {
asyncParams: () => Promise<AirdropERC20WithSignatureParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.req, resolvedOptions.signature] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,165 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropERC721" function.
*/
export type AirdropERC721Params = WithOverrides<{
tokenAddress: AbiParameterToPrimitiveType<{
name: "_tokenAddress";
type: "address";
internalType: "address";
}>;
contents: AbiParameterToPrimitiveType<{
name: "_contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC721[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "tokenId"; type: "uint256"; internalType: "uint256" },
];
}>;
}>;
export const FN_SELECTOR = "0x6d582ebe" as const;
const FN_INPUTS = [
{
name: "_tokenAddress",
type: "address",
internalType: "address",
},
{
name: "_contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC721[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "tokenId",
type: "uint256",
internalType: "uint256",
},
],
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropERC721` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropERC721` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropERC721Supported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropERC721Supported(contract);
* ```
*/
export async function isAirdropERC721Supported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropERC721" function.
* @param options - The options for the airdropERC721 function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC721Params } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC721Params({
* tokenAddress: ...,
* contents: ...,
* });
* ```
*/
export function encodeAirdropERC721Params(options: AirdropERC721Params) {
return encodeAbiParameters(FN_INPUTS, [
options.tokenAddress,
options.contents,
]);
}
/**
* Encodes the "airdropERC721" function into a Hex string with its parameters.
* @param options - The options for the airdropERC721 function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC721 } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC721({
* tokenAddress: ...,
* contents: ...,
* });
* ```
*/
export function encodeAirdropERC721(options: AirdropERC721Params) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropERC721Params(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropERC721" function on the contract.
* @param options - The options for the "airdropERC721" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropERC721 } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropERC721({
* contract,
* tokenAddress: ...,
* contents: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropERC721(
options: BaseTransactionOptions<
| AirdropERC721Params
| {
asyncParams: () => Promise<AirdropERC721Params>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.tokenAddress, resolvedOptions.contents] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,198 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropERC721WithSignature" function.
*/
export type AirdropERC721WithSignatureParams = WithOverrides<{
req: AbiParameterToPrimitiveType<{
name: "req";
type: "tuple";
internalType: "struct Airdrop.AirdropRequestERC721";
components: [
{ name: "uid"; type: "bytes32"; internalType: "bytes32" },
{ name: "tokenAddress"; type: "address"; internalType: "address" },
{ name: "expirationTimestamp"; type: "uint256"; internalType: "uint256" },
{
name: "contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC721[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "tokenId"; type: "uint256"; internalType: "uint256" },
];
},
];
}>;
signature: AbiParameterToPrimitiveType<{
name: "signature";
type: "bytes";
internalType: "bytes";
}>;
}>;
export const FN_SELECTOR = "0xb654a6f3" as const;
const FN_INPUTS = [
{
name: "req",
type: "tuple",
internalType: "struct Airdrop.AirdropRequestERC721",
components: [
{
name: "uid",
type: "bytes32",
internalType: "bytes32",
},
{
name: "tokenAddress",
type: "address",
internalType: "address",
},
{
name: "expirationTimestamp",
type: "uint256",
internalType: "uint256",
},
{
name: "contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC721[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "tokenId",
type: "uint256",
internalType: "uint256",
},
],
},
],
},
{
name: "signature",
type: "bytes",
internalType: "bytes",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropERC721WithSignature` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropERC721WithSignature` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropERC721WithSignatureSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropERC721WithSignatureSupported(contract);
* ```
*/
export async function isAirdropERC721WithSignatureSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropERC721WithSignature" function.
* @param options - The options for the airdropERC721WithSignature function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC721WithSignatureParams } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC721WithSignatureParams({
* req: ...,
* signature: ...,
* });
* ```
*/
export function encodeAirdropERC721WithSignatureParams(
options: AirdropERC721WithSignatureParams,
) {
return encodeAbiParameters(FN_INPUTS, [options.req, options.signature]);
}
/**
* Encodes the "airdropERC721WithSignature" function into a Hex string with its parameters.
* @param options - The options for the airdropERC721WithSignature function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropERC721WithSignature } "thirdweb/extensions/airdrop";
* const result = encodeAirdropERC721WithSignature({
* req: ...,
* signature: ...,
* });
* ```
*/
export function encodeAirdropERC721WithSignature(
options: AirdropERC721WithSignatureParams,
) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropERC721WithSignatureParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropERC721WithSignature" function on the contract.
* @param options - The options for the "airdropERC721WithSignature" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropERC721WithSignature } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropERC721WithSignature({
* contract,
* req: ...,
* signature: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropERC721WithSignature(
options: BaseTransactionOptions<
| AirdropERC721WithSignatureParams
| {
asyncParams: () => Promise<AirdropERC721WithSignatureParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.req, resolvedOptions.signature] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,151 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "airdropNativeToken" function.
*/
export type AirdropNativeTokenParams = WithOverrides<{
contents: AbiParameterToPrimitiveType<{
name: "_contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC20[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
}>;
}>;
export const FN_SELECTOR = "0x0d5818f7" as const;
const FN_INPUTS = [
{
name: "_contents",
type: "tuple[]",
internalType: "struct Airdrop.AirdropContentERC20[]",
components: [
{
name: "recipient",
type: "address",
internalType: "address",
},
{
name: "amount",
type: "uint256",
internalType: "uint256",
},
],
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `airdropNativeToken` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `airdropNativeToken` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isAirdropNativeTokenSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isAirdropNativeTokenSupported(contract);
* ```
*/
export async function isAirdropNativeTokenSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "airdropNativeToken" function.
* @param options - The options for the airdropNativeToken function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropNativeTokenParams } "thirdweb/extensions/airdrop";
* const result = encodeAirdropNativeTokenParams({
* contents: ...,
* });
* ```
*/
export function encodeAirdropNativeTokenParams(
options: AirdropNativeTokenParams,
) {
return encodeAbiParameters(FN_INPUTS, [options.contents]);
}
/**
* Encodes the "airdropNativeToken" function into a Hex string with its parameters.
* @param options - The options for the airdropNativeToken function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeAirdropNativeToken } "thirdweb/extensions/airdrop";
* const result = encodeAirdropNativeToken({
* contents: ...,
* });
* ```
*/
export function encodeAirdropNativeToken(options: AirdropNativeTokenParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeAirdropNativeTokenParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "airdropNativeToken" function on the contract.
* @param options - The options for the "airdropNativeToken" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { airdropNativeToken } from "thirdweb/extensions/airdrop";
*
* const transaction = airdropNativeToken({
* contract,
* contents: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function airdropNativeToken(
options: BaseTransactionOptions<
| AirdropNativeTokenParams
| {
asyncParams: () => Promise<AirdropNativeTokenParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.contents] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,195 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "claimERC1155" function.
*/
export type ClaimERC1155Params = WithOverrides<{
token: AbiParameterToPrimitiveType<{
name: "_token";
type: "address";
internalType: "address";
}>;
receiver: AbiParameterToPrimitiveType<{
name: "_receiver";
type: "address";
internalType: "address";
}>;
tokenId: AbiParameterToPrimitiveType<{
name: "_tokenId";
type: "uint256";
internalType: "uint256";
}>;
quantity: AbiParameterToPrimitiveType<{
name: "_quantity";
type: "uint256";
internalType: "uint256";
}>;
proofs: AbiParameterToPrimitiveType<{
name: "_proofs";
type: "bytes32[]";
internalType: "bytes32[]";
}>;
}>;
export const FN_SELECTOR = "0xc6fa26ab" as const;
const FN_INPUTS = [
{
name: "_token",
type: "address",
internalType: "address",
},
{
name: "_receiver",
type: "address",
internalType: "address",
},
{
name: "_tokenId",
type: "uint256",
internalType: "uint256",
},
{
name: "_quantity",
type: "uint256",
internalType: "uint256",
},
{
name: "_proofs",
type: "bytes32[]",
internalType: "bytes32[]",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `claimERC1155` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `claimERC1155` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isClaimERC1155Supported } from "thirdweb/extensions/airdrop";
*
* const supported = await isClaimERC1155Supported(contract);
* ```
*/
export async function isClaimERC1155Supported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "claimERC1155" function.
* @param options - The options for the claimERC1155 function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeClaimERC1155Params } "thirdweb/extensions/airdrop";
* const result = encodeClaimERC1155Params({
* token: ...,
* receiver: ...,
* tokenId: ...,
* quantity: ...,
* proofs: ...,
* });
* ```
*/
export function encodeClaimERC1155Params(options: ClaimERC1155Params) {
return encodeAbiParameters(FN_INPUTS, [
options.token,
options.receiver,
options.tokenId,
options.quantity,
options.proofs,
]);
}
/**
* Encodes the "claimERC1155" function into a Hex string with its parameters.
* @param options - The options for the claimERC1155 function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeClaimERC1155 } "thirdweb/extensions/airdrop";
* const result = encodeClaimERC1155({
* token: ...,
* receiver: ...,
* tokenId: ...,
* quantity: ...,
* proofs: ...,
* });
* ```
*/
export function encodeClaimERC1155(options: ClaimERC1155Params) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeClaimERC1155Params(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "claimERC1155" function on the contract.
* @param options - The options for the "claimERC1155" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { claimERC1155 } from "thirdweb/extensions/airdrop";
*
* const transaction = claimERC1155({
* contract,
* token: ...,
* receiver: ...,
* tokenId: ...,
* quantity: ...,
* proofs: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function claimERC1155(
options: BaseTransactionOptions<
| ClaimERC1155Params
| {
asyncParams: () => Promise<ClaimERC1155Params>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [
resolvedOptions.token,
resolvedOptions.receiver,
resolvedOptions.tokenId,
resolvedOptions.quantity,
resolvedOptions.proofs,
] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,180 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "claimERC20" function.
*/
export type ClaimERC20Params = WithOverrides<{
token: AbiParameterToPrimitiveType<{
name: "_token";
type: "address";
internalType: "address";
}>;
receiver: AbiParameterToPrimitiveType<{
name: "_receiver";
type: "address";
internalType: "address";
}>;
quantity: AbiParameterToPrimitiveType<{
name: "_quantity";
type: "uint256";
internalType: "uint256";
}>;
proofs: AbiParameterToPrimitiveType<{
name: "_proofs";
type: "bytes32[]";
internalType: "bytes32[]";
}>;
}>;
export const FN_SELECTOR = "0xecf3d3d4" as const;
const FN_INPUTS = [
{
name: "_token",
type: "address",
internalType: "address",
},
{
name: "_receiver",
type: "address",
internalType: "address",
},
{
name: "_quantity",
type: "uint256",
internalType: "uint256",
},
{
name: "_proofs",
type: "bytes32[]",
internalType: "bytes32[]",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `claimERC20` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `claimERC20` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isClaimERC20Supported } from "thirdweb/extensions/airdrop";
*
* const supported = await isClaimERC20Supported(contract);
* ```
*/
export async function isClaimERC20Supported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "claimERC20" function.
* @param options - The options for the claimERC20 function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeClaimERC20Params } "thirdweb/extensions/airdrop";
* const result = encodeClaimERC20Params({
* token: ...,
* receiver: ...,
* quantity: ...,
* proofs: ...,
* });
* ```
*/
export function encodeClaimERC20Params(options: ClaimERC20Params) {
return encodeAbiParameters(FN_INPUTS, [
options.token,
options.receiver,
options.quantity,
options.proofs,
]);
}
/**
* Encodes the "claimERC20" function into a Hex string with its parameters.
* @param options - The options for the claimERC20 function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeClaimERC20 } "thirdweb/extensions/airdrop";
* const result = encodeClaimERC20({
* token: ...,
* receiver: ...,
* quantity: ...,
* proofs: ...,
* });
* ```
*/
export function encodeClaimERC20(options: ClaimERC20Params) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeClaimERC20Params(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "claimERC20" function on the contract.
* @param options - The options for the "claimERC20" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { claimERC20 } from "thirdweb/extensions/airdrop";
*
* const transaction = claimERC20({
* contract,
* token: ...,
* receiver: ...,
* quantity: ...,
* proofs: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function claimERC20(
options: BaseTransactionOptions<
| ClaimERC20Params
| {
asyncParams: () => Promise<ClaimERC20Params>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [
resolvedOptions.token,
resolvedOptions.receiver,
resolvedOptions.quantity,
resolvedOptions.proofs,
] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,180 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "claimERC721" function.
*/
export type ClaimERC721Params = WithOverrides<{
token: AbiParameterToPrimitiveType<{
name: "_token";
type: "address";
internalType: "address";
}>;
receiver: AbiParameterToPrimitiveType<{
name: "_receiver";
type: "address";
internalType: "address";
}>;
tokenId: AbiParameterToPrimitiveType<{
name: "_tokenId";
type: "uint256";
internalType: "uint256";
}>;
proofs: AbiParameterToPrimitiveType<{
name: "_proofs";
type: "bytes32[]";
internalType: "bytes32[]";
}>;
}>;
export const FN_SELECTOR = "0x1290be10" as const;
const FN_INPUTS = [
{
name: "_token",
type: "address",
internalType: "address",
},
{
name: "_receiver",
type: "address",
internalType: "address",
},
{
name: "_tokenId",
type: "uint256",
internalType: "uint256",
},
{
name: "_proofs",
type: "bytes32[]",
internalType: "bytes32[]",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `claimERC721` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `claimERC721` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isClaimERC721Supported } from "thirdweb/extensions/airdrop";
*
* const supported = await isClaimERC721Supported(contract);
* ```
*/
export async function isClaimERC721Supported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "claimERC721" function.
* @param options - The options for the claimERC721 function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeClaimERC721Params } "thirdweb/extensions/airdrop";
* const result = encodeClaimERC721Params({
* token: ...,
* receiver: ...,
* tokenId: ...,
* proofs: ...,
* });
* ```
*/
export function encodeClaimERC721Params(options: ClaimERC721Params) {
return encodeAbiParameters(FN_INPUTS, [
options.token,
options.receiver,
options.tokenId,
options.proofs,
]);
}
/**
* Encodes the "claimERC721" function into a Hex string with its parameters.
* @param options - The options for the claimERC721 function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeClaimERC721 } "thirdweb/extensions/airdrop";
* const result = encodeClaimERC721({
* token: ...,
* receiver: ...,
* tokenId: ...,
* proofs: ...,
* });
* ```
*/
export function encodeClaimERC721(options: ClaimERC721Params) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeClaimERC721Params(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "claimERC721" function on the contract.
* @param options - The options for the "claimERC721" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { claimERC721 } from "thirdweb/extensions/airdrop";
*
* const transaction = claimERC721({
* contract,
* token: ...,
* receiver: ...,
* tokenId: ...,
* proofs: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function claimERC721(
options: BaseTransactionOptions<
| ClaimERC721Params
| {
asyncParams: () => Promise<ClaimERC721Params>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [
resolvedOptions.token,
resolvedOptions.receiver,
resolvedOptions.tokenId,
resolvedOptions.proofs,
] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,131 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "initialize" function.
*/
export type InitializeParams = WithOverrides<{
defaultAdmin: AbiParameterToPrimitiveType<{
name: "_defaultAdmin";
type: "address";
internalType: "address";
}>;
}>;
export const FN_SELECTOR = "0xc4d66de8" as const;
const FN_INPUTS = [
{
name: "_defaultAdmin",
type: "address",
internalType: "address",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `initialize` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `initialize` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isInitializeSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isInitializeSupported(contract);
* ```
*/
export async function isInitializeSupported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "initialize" function.
* @param options - The options for the initialize function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeInitializeParams } "thirdweb/extensions/airdrop";
* const result = encodeInitializeParams({
* defaultAdmin: ...,
* });
* ```
*/
export function encodeInitializeParams(options: InitializeParams) {
return encodeAbiParameters(FN_INPUTS, [options.defaultAdmin]);
}
/**
* Encodes the "initialize" function into a Hex string with its parameters.
* @param options - The options for the initialize function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeInitialize } "thirdweb/extensions/airdrop";
* const result = encodeInitialize({
* defaultAdmin: ...,
* });
* ```
*/
export function encodeInitialize(options: InitializeParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeInitializeParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "initialize" function on the contract.
* @param options - The options for the "initialize" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { initialize } from "thirdweb/extensions/airdrop";
*
* const transaction = initialize({
* contract,
* defaultAdmin: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function initialize(
options: BaseTransactionOptions<
| InitializeParams
| {
asyncParams: () => Promise<InitializeParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.defaultAdmin] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,128 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "setContractURI" function.
*/
export type SetContractURIParams = WithOverrides<{
uri: AbiParameterToPrimitiveType<{ type: "string"; name: "_uri" }>;
}>;
export const FN_SELECTOR = "0x938e3d7b" as const;
const FN_INPUTS = [
{
type: "string",
name: "_uri",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `setContractURI` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `setContractURI` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isSetContractURISupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isSetContractURISupported(contract);
* ```
*/
export async function isSetContractURISupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "setContractURI" function.
* @param options - The options for the setContractURI function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeSetContractURIParams } "thirdweb/extensions/airdrop";
* const result = encodeSetContractURIParams({
* uri: ...,
* });
* ```
*/
export function encodeSetContractURIParams(options: SetContractURIParams) {
return encodeAbiParameters(FN_INPUTS, [options.uri]);
}
/**
* Encodes the "setContractURI" function into a Hex string with its parameters.
* @param options - The options for the setContractURI function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeSetContractURI } "thirdweb/extensions/airdrop";
* const result = encodeSetContractURI({
* uri: ...,
* });
* ```
*/
export function encodeSetContractURI(options: SetContractURIParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeSetContractURIParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "setContractURI" function on the contract.
* @param options - The options for the "setContractURI" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { setContractURI } from "thirdweb/extensions/airdrop";
*
* const transaction = setContractURI({
* contract,
* uri: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function setContractURI(
options: BaseTransactionOptions<
| SetContractURIParams
| {
asyncParams: () => Promise<SetContractURIParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.uri] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,167 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "setMerkleRoot" function.
*/
export type SetMerkleRootParams = WithOverrides<{
token: AbiParameterToPrimitiveType<{
name: "_token";
type: "address";
internalType: "address";
}>;
tokenMerkleRoot: AbiParameterToPrimitiveType<{
name: "_tokenMerkleRoot";
type: "bytes32";
internalType: "bytes32";
}>;
resetClaimStatus: AbiParameterToPrimitiveType<{
name: "_resetClaimStatus";
type: "bool";
internalType: "bool";
}>;
}>;
export const FN_SELECTOR = "0x8259a87b" as const;
const FN_INPUTS = [
{
name: "_token",
type: "address",
internalType: "address",
},
{
name: "_tokenMerkleRoot",
type: "bytes32",
internalType: "bytes32",
},
{
name: "_resetClaimStatus",
type: "bool",
internalType: "bool",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `setMerkleRoot` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `setMerkleRoot` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isSetMerkleRootSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isSetMerkleRootSupported(contract);
* ```
*/
export async function isSetMerkleRootSupported(
contract: ThirdwebContract<any>,
) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "setMerkleRoot" function.
* @param options - The options for the setMerkleRoot function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeSetMerkleRootParams } "thirdweb/extensions/airdrop";
* const result = encodeSetMerkleRootParams({
* token: ...,
* tokenMerkleRoot: ...,
* resetClaimStatus: ...,
* });
* ```
*/
export function encodeSetMerkleRootParams(options: SetMerkleRootParams) {
return encodeAbiParameters(FN_INPUTS, [
options.token,
options.tokenMerkleRoot,
options.resetClaimStatus,
]);
}
/**
* Encodes the "setMerkleRoot" function into a Hex string with its parameters.
* @param options - The options for the setMerkleRoot function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeSetMerkleRoot } "thirdweb/extensions/airdrop";
* const result = encodeSetMerkleRoot({
* token: ...,
* tokenMerkleRoot: ...,
* resetClaimStatus: ...,
* });
* ```
*/
export function encodeSetMerkleRoot(options: SetMerkleRootParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeSetMerkleRootParams(options).slice(
2,
)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "setMerkleRoot" function on the contract.
* @param options - The options for the "setMerkleRoot" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { setMerkleRoot } from "thirdweb/extensions/airdrop";
*
* const transaction = setMerkleRoot({
* contract,
* token: ...,
* tokenMerkleRoot: ...,
* resetClaimStatus: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function setMerkleRoot(
options: BaseTransactionOptions<
| SetMerkleRootParams
| {
asyncParams: () => Promise<SetMerkleRootParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [
resolvedOptions.token,
resolvedOptions.tokenMerkleRoot,
resolvedOptions.resetClaimStatus,
] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,129 @@
import type { AbiParameterToPrimitiveType } from "abitype";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../../../transaction/types.js";
import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js";
import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js";
import { once } from "../../../../../utils/promise/once.js";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
/**
* Represents the parameters for the "setOwner" function.
*/
export type SetOwnerParams = WithOverrides<{
newOwner: AbiParameterToPrimitiveType<{
name: "_newOwner";
type: "address";
internalType: "address";
}>;
}>;
export const FN_SELECTOR = "0x13af4035" as const;
const FN_INPUTS = [
{
name: "_newOwner",
type: "address",
internalType: "address",
},
] as const;
const FN_OUTPUTS = [] as const;
/**
* Checks if the `setOwner` method is supported by the given contract.
* @param contract The ThirdwebContract.
* @returns A promise that resolves to a boolean indicating if the `setOwner` method is supported.
* @extension AIRDROP
* @example
* ```ts
* import { isSetOwnerSupported } from "thirdweb/extensions/airdrop";
*
* const supported = await isSetOwnerSupported(contract);
* ```
*/
export async function isSetOwnerSupported(contract: ThirdwebContract<any>) {
return detectMethod({
contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
});
}
/**
* Encodes the parameters for the "setOwner" function.
* @param options - The options for the setOwner function.
* @returns The encoded ABI parameters.
* @extension AIRDROP
* @example
* ```ts
* import { encodeSetOwnerParams } "thirdweb/extensions/airdrop";
* const result = encodeSetOwnerParams({
* newOwner: ...,
* });
* ```
*/
export function encodeSetOwnerParams(options: SetOwnerParams) {
return encodeAbiParameters(FN_INPUTS, [options.newOwner]);
}
/**
* Encodes the "setOwner" function into a Hex string with its parameters.
* @param options - The options for the setOwner function.
* @returns The encoded hexadecimal string.
* @extension AIRDROP
* @example
* ```ts
* import { encodeSetOwner } "thirdweb/extensions/airdrop";
* const result = encodeSetOwner({
* newOwner: ...,
* });
* ```
*/
export function encodeSetOwner(options: SetOwnerParams) {
// we do a "manual" concat here to avoid the overhead of the "concatHex" function
// we can do this because we know the specific formats of the values
return (FN_SELECTOR +
encodeSetOwnerParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`;
}
/**
* Calls the "setOwner" function on the contract.
* @param options - The options for the "setOwner" function.
* @returns A prepared transaction object.
* @extension AIRDROP
* @example
* ```ts
* import { setOwner } from "thirdweb/extensions/airdrop";
*
* const transaction = setOwner({
* contract,
* newOwner: ...,
* });
*
* // Send the transaction
* ...
*
* ```
*/
export function setOwner(
options: BaseTransactionOptions<
| SetOwnerParams
| {
asyncParams: () => Promise<SetOwnerParams>;
}
>,
) {
const asyncOptions = once(async () => {
return "asyncParams" in options ? await options.asyncParams() : options;
});
return prepareContractCall({
contract: options.contract,
method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
params: async () => {
const resolvedOptions = await asyncOptions();
return [resolvedOptions.newOwner] as const;
},
value: async () => (await asyncOptions()).overrides?.value,
});
}
@@ -0,0 +1,150 @@
import { beforeAll, describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_A,
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../../test/src/test-wallets.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import {
balanceOf,
setApprovalForAll,
} from "../../../exports/extensions/erc1155.js";
import { sendTransaction } from "../../../transaction/actions/send-transaction.js";
import { mintTo } from "../../erc1155/write/mintTo.js";
import { deployERC1155Contract } from "../../prebuilts/deploy-erc1155.js";
import { deployPublishedContract } from "../../prebuilts/deploy-published.js";
import {
airdropERC1155WithSignature,
generateAirdropSignatureERC1155,
} from "./airdropERC1155WithSignature.js";
// skip this test suite if there is no secret key available to test with
// TODO: remove reliance on secret key during unit tests entirely
describe.runIf(process.env.TW_SECRET_KEY)(
"generateAirdropSignatureERC11551155",
() => {
let airdropContract: ThirdwebContract;
let erc1155TokenContract: ThirdwebContract;
beforeAll(async () => {
airdropContract = getContract({
address: await deployPublishedContract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
contractId: "Airdrop",
contractParams: [TEST_ACCOUNT_A.address],
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
erc1155TokenContract = getContract({
address: await deployERC1155Contract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
params: {
name: "Test",
symbol: "TST",
},
type: "TokenERC1155",
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
const mintTransactions = [
mintTo({
contract: erc1155TokenContract,
to: TEST_ACCOUNT_A.address,
supply: 100000n,
nft: {
name: "Test 0",
},
}),
mintTo({
contract: erc1155TokenContract,
to: TEST_ACCOUNT_A.address,
supply: 100000n,
nft: {
name: "Test 1",
},
}),
];
for (const tx of mintTransactions) {
await sendTransaction({
transaction: tx,
account: TEST_ACCOUNT_A,
});
}
const approvalTx = setApprovalForAll({
contract: erc1155TokenContract,
operator: airdropContract.address,
approved: true,
});
await sendTransaction({
transaction: approvalTx,
account: TEST_ACCOUNT_A,
});
}, 60000);
it("should send airdrop of ERC1155 tokens with signature", async () => {
const contents = [
{ recipient: TEST_ACCOUNT_B.address, tokenId: 0n, amount: 10n },
{ recipient: TEST_ACCOUNT_C.address, tokenId: 0n, amount: 12n },
{ recipient: TEST_ACCOUNT_D.address, tokenId: 1n, amount: 5n },
];
const { req, signature } = await generateAirdropSignatureERC1155({
airdropRequest: {
tokenAddress: erc1155TokenContract.address,
contents,
},
account: TEST_ACCOUNT_A,
contract: airdropContract,
});
const transaction = airdropERC1155WithSignature({
contract: airdropContract,
req,
signature,
});
const { transactionHash } = await sendTransaction({
transaction,
account: TEST_ACCOUNT_A,
});
const balanceB = await balanceOf({
contract: erc1155TokenContract,
owner: TEST_ACCOUNT_B.address,
tokenId: 0n,
});
const balanceC = await balanceOf({
contract: erc1155TokenContract,
owner: TEST_ACCOUNT_C.address,
tokenId: 0n,
});
const balanceD = await balanceOf({
contract: erc1155TokenContract,
owner: TEST_ACCOUNT_D.address,
tokenId: 1n,
});
expect(balanceB).to.equal(10n);
expect(balanceC).to.equal(12n);
expect(balanceD).to.equal(5n);
expect(transactionHash.length).toBe(66);
});
},
);
@@ -0,0 +1,143 @@
import type { AbiParameterToPrimitiveType, Address } from "abitype";
import type { ThirdwebContract } from "../../../contract/contract.js";
import { dateToSeconds, tenYearsFromNow } from "../../../utils/date.js";
import type { Hex } from "../../../utils/encoding/hex.js";
import { randomBytes32 } from "../../../utils/uuid.js";
import type { Account } from "../../../wallets/interfaces/wallet.js";
import { airdropERC1155WithSignature as generatedAirdropERC1155WithSignature } from "../__generated__/Airdrop/write/airdropERC1155WithSignature.js";
/**
* Airdrops ERC1155 tokens to a list of recipients, with the request signed by admin
* @param options - The transaction options.
* @example
* ```ts
* import { airdropERC1155WithSignature, generateAirdropSignatureERC1155 } from "thirdweb/extensions/airdrop";
*
* const { req, signature } = await generateAirdropSignatureERC1155(...)
*
* const transaction = airdropERC1155WithSignature({
* contract,
* req,
* signature,
* });
* await sendTransaction({ transaction, account });
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export const airdropERC1155WithSignature = generatedAirdropERC1155WithSignature;
export type GenerateAirdropSignatureOptions = {
account: Account;
contract: ThirdwebContract;
airdropRequest: GenerateReqInput;
};
/**
* Generates the req and signature for sending ERC1155 airdrop.
* @param options - The options for the airdrop.
* @example
* ```ts
* import { airdropERC1155WithSignature, generateAirdropSignatureERC1155 } from "thirdweb/extensions/airdrop";
*
* // list of recipients, tokenIds and amounts to airdrop for each recipient
* const contents = [
* { recipient: "0x...", tokenId: 0, amount: 10n },
* { recipient: "0x...", tokenId: 0, amount: 15n },
* { recipient: "0x...", tokenId: 0, amount: 20n },
* ];
*
* const { req, signature } = await generateAirdropSignatureERC1155({
* account,
* contract,
* airdropRequest: {
* tokenAddress: "0x...", // address of the ERC1155 token to airdrop
* contents
* },
* });
*
* const transaction = airdropERC1155WithSignature({
* contract,
* req,
* signature,
* });
* await sendTransaction({ transaction, account });
* ```
* @extension Airdrop
* @returns A promise that resolves to the req and signature.
*/
export async function generateAirdropSignatureERC1155(
options: GenerateAirdropSignatureOptions,
) {
const { airdropRequest, account, contract } = options;
const tokenAddress = airdropRequest.tokenAddress;
const contents = airdropRequest.contents;
const uid = airdropRequest.uid || (await randomBytes32());
const endTime = airdropRequest.expirationTimestamp || tenYearsFromNow();
const req: ReqType = {
uid,
tokenAddress,
expirationTimestamp: dateToSeconds(endTime),
contents,
};
const signature = await account.signTypedData({
domain: {
name: "Airdrop",
version: "1",
chainId: contract.chain.id,
verifyingContract: contract.address as Hex,
},
types: { AirdropRequestERC1155, AirdropContentERC1155 },
primaryType: "AirdropRequestERC1155",
message: req,
});
return { req, signature };
}
type ContentType = AbiParameterToPrimitiveType<{
type: "tuple[]";
name: "contents";
components: typeof AirdropContentERC1155;
}>;
type ReqType = AbiParameterToPrimitiveType<{
type: "tuple";
name: "req";
components: [
{ name: "uid"; type: "bytes32"; internalType: "bytes32" },
{ name: "tokenAddress"; type: "address"; internalType: "address" },
{ name: "expirationTimestamp"; type: "uint256"; internalType: "uint256" },
{
name: "contents";
type: "tuple[]";
internalType: "struct Airdrop.AirdropContentERC1155[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "tokenId"; type: "uint256"; internalType: "uint256" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
},
];
}>;
type GenerateReqInput = {
uid?: Hex;
tokenAddress: Address;
expirationTimestamp?: Date;
contents: ContentType;
};
export const AirdropContentERC1155 = [
{ name: "recipient", type: "address" },
{ name: "tokenId", type: "uint256" },
{ name: "amount", type: "uint256" },
] as const;
export const AirdropRequestERC1155 = [
{ name: "uid", type: "bytes32" },
{ name: "tokenAddress", type: "address" },
{ name: "expirationTimestamp", type: "uint256" },
{ name: "contents", type: "AirdropContentERC1155[]" },
] as const;
@@ -0,0 +1,144 @@
import { beforeAll, describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_A,
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../../test/src/test-wallets.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import { sendTransaction } from "../../../transaction/actions/send-transaction.js";
import { getBalance } from "../../erc20/read/getBalance.js";
import { approve } from "../../erc20/write/approve.js";
import { mintTo } from "../../erc20/write/mintTo.js";
import { deployERC20Contract } from "../../prebuilts/deploy-erc20.js";
import { deployPublishedContract } from "../../prebuilts/deploy-published.js";
import {
airdropERC20WithSignature,
generateAirdropSignatureERC20,
} from "./airdropERC20WithSignature.js";
// skip this test suite if there is no secret key available to test with
// TODO: remove reliance on secret key during unit tests entirely
describe.runIf(process.env.TW_SECRET_KEY)(
"generateAirdropSignatureERC2020",
() => {
let airdropContract: ThirdwebContract;
let erc20TokenContract: ThirdwebContract;
beforeAll(async () => {
airdropContract = getContract({
address: await deployPublishedContract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
contractId: "Airdrop",
contractParams: [TEST_ACCOUNT_A.address],
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
erc20TokenContract = getContract({
address: await deployERC20Contract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
params: {
name: "TestToken",
symbol: "TSTT",
},
type: "TokenERC20",
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
const mintTx = mintTo({
contract: erc20TokenContract,
to: TEST_ACCOUNT_A.address,
amountWei: 1000n,
});
await sendTransaction({
transaction: mintTx,
account: TEST_ACCOUNT_A,
});
const approvalTx = await approve({
contract: erc20TokenContract,
spender: airdropContract.address,
amountWei: 1000n,
});
await sendTransaction({
transaction: approvalTx,
account: TEST_ACCOUNT_A,
});
}, 60000);
it("should send airdrop of ERC20 tokens with signature", async () => {
const contents = [
{ recipient: TEST_ACCOUNT_B.address, amount: 10n },
{ recipient: TEST_ACCOUNT_C.address, amount: 15n },
{ recipient: TEST_ACCOUNT_D.address, amount: 20n },
];
const { req, signature } = await generateAirdropSignatureERC20({
airdropRequest: {
tokenAddress: erc20TokenContract.address,
contents,
},
account: TEST_ACCOUNT_A,
contract: airdropContract,
});
const transaction = airdropERC20WithSignature({
contract: airdropContract,
req,
signature,
});
const { transactionHash } = await sendTransaction({
transaction,
account: TEST_ACCOUNT_A,
});
const balanceB = (
await getBalance({
contract: erc20TokenContract,
address: TEST_ACCOUNT_B.address,
})
).value;
const balanceC = (
await getBalance({
contract: erc20TokenContract,
address: TEST_ACCOUNT_C.address,
})
).value;
const balanceD = (
await getBalance({
contract: erc20TokenContract,
address: TEST_ACCOUNT_D.address,
})
).value;
// admin balance
const balanceA = (
await getBalance({
contract: erc20TokenContract,
address: TEST_ACCOUNT_A.address,
})
).value;
expect(balanceB).to.equal(10n);
expect(balanceC).to.equal(15n);
expect(balanceD).to.equal(20n);
expect(balanceA).to.equal(1000n - balanceB - balanceC - balanceD);
expect(transactionHash.length).toBe(66);
});
},
);
@@ -0,0 +1,141 @@
import type { AbiParameterToPrimitiveType, Address } from "abitype";
import type { ThirdwebContract } from "../../../contract/contract.js";
import { dateToSeconds, tenYearsFromNow } from "../../../utils/date.js";
import type { Hex } from "../../../utils/encoding/hex.js";
import { randomBytes32 } from "../../../utils/uuid.js";
import type { Account } from "../../../wallets/interfaces/wallet.js";
import { airdropERC20WithSignature as generatedAirdropERC20WithSignature } from "../__generated__/Airdrop/write/airdropERC20WithSignature.js";
/**
* Airdrops ERC20 tokens to a list of recipients, with the request signed by admin
* @param options - The transaction options.
* @example
* ```ts
* import { airdropERC20WithSignature, generateAirdropSignatureERC20 } from "thirdweb/extensions/airdrop";
*
* const { req, signature } = await generateAirdropSignatureERC20(...)
*
* const transaction = airdropERC20WithSignature({
* contract,
* req,
* signature,
* });
* await sendTransaction({ transaction, account });
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export const airdropERC20WithSignature = generatedAirdropERC20WithSignature;
export type GenerateAirdropSignatureOptions = {
account: Account;
contract: ThirdwebContract;
airdropRequest: GenerateReqInput;
};
/**
* Generates the req and signature for sending ERC20 airdrop.
* @param options - The options for the airdrop.
* @example
* ```ts
* import { airdropERC20WithSignature, generateAirdropSignatureERC20 } from "thirdweb/extensions/airdrop";
*
* // list of recipients and amounts to airdrop for each recipient
* const contents = [
* { recipient: "0x...", amount: 10n }, // amount in wei
* { recipient: "0x...", amount: 15n }, // amount in wei
* { recipient: "0x...", amount: 20n }, // amount in wei
* ];
*
* const { req, signature } = await generateAirdropSignatureERC20({
* account,
* contract,
* airdropRequest: {
* tokenAddress: "0x...", // address of the ERC20 token to airdrop
* contents
* },
* });
*
* const transaction = airdropERC20WithSignature({
* contract,
* req,
* signature,
* });
* await sendTransaction({ transaction, account });
* ```
* @extension Airdrop
* @returns A promise that resolves to the req and signature.
*/
export async function generateAirdropSignatureERC20(
options: GenerateAirdropSignatureOptions,
) {
const { airdropRequest, account, contract } = options;
const tokenAddress = airdropRequest.tokenAddress;
const contents = airdropRequest.contents;
const uid = airdropRequest.uid || (await randomBytes32());
const endTime = airdropRequest.expirationTimestamp || tenYearsFromNow();
const req: ReqType = {
uid,
tokenAddress,
expirationTimestamp: dateToSeconds(endTime),
contents,
};
const signature = await account.signTypedData({
domain: {
name: "Airdrop",
version: "1",
chainId: contract.chain.id,
verifyingContract: contract.address as Hex,
},
types: { AirdropRequestERC20, AirdropContentERC20 },
primaryType: "AirdropRequestERC20",
message: req,
});
return { req, signature };
}
type ContentType = AbiParameterToPrimitiveType<{
type: "tuple[]";
name: "contents";
components: typeof AirdropContentERC20;
}>;
type ReqType = AbiParameterToPrimitiveType<{
type: "tuple";
name: "req";
components: [
{ name: "uid"; type: "bytes32"; internalType: "bytes32" },
{ name: "tokenAddress"; type: "address"; internalType: "address" },
{ name: "expirationTimestamp"; type: "uint256"; internalType: "uint256" },
{
name: "contents";
type: "tuple[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "amount"; type: "uint256"; internalType: "uint256" },
];
},
];
}>;
type GenerateReqInput = {
uid?: Hex;
tokenAddress: Address;
expirationTimestamp?: Date;
contents: ContentType;
};
export const AirdropContentERC20 = [
{ name: "recipient", type: "address" },
{ name: "amount", type: "uint256" },
] as const;
export const AirdropRequestERC20 = [
{ name: "uid", type: "bytes32" },
{ name: "tokenAddress", type: "address" },
{ name: "expirationTimestamp", type: "uint256" },
{ name: "contents", type: "AirdropContentERC20[]" },
] as const;
@@ -0,0 +1,159 @@
import { beforeAll, describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_A,
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../../test/src/test-wallets.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import {
ownerOf,
setApprovalForAll,
} from "../../../exports/extensions/erc721.js";
import { sendTransaction } from "../../../transaction/actions/send-transaction.js";
import { mintTo } from "../../erc721/write/mintTo.js";
import { deployERC721Contract } from "../../prebuilts/deploy-erc721.js";
import { deployPublishedContract } from "../../prebuilts/deploy-published.js";
import {
airdropERC721WithSignature,
generateAirdropSignatureERC721,
} from "./airdropERC721WithSignature.js";
// skip this test suite if there is no secret key available to test with
// TODO: remove reliance on secret key during unit tests entirely
describe.runIf(process.env.TW_SECRET_KEY)(
"generateAirdropSignatureERC721721",
() => {
let airdropContract: ThirdwebContract;
let erc721TokenContract: ThirdwebContract;
beforeAll(async () => {
airdropContract = getContract({
address: await deployPublishedContract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
contractId: "Airdrop",
contractParams: [TEST_ACCOUNT_A.address],
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
erc721TokenContract = getContract({
address: await deployERC721Contract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
params: {
name: "Test",
symbol: "TST",
},
type: "TokenERC721",
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
const mintTransactions = [
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 0",
},
}),
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 1",
},
}),
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 2",
},
}),
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 3",
},
}),
];
for (const tx of mintTransactions) {
await sendTransaction({
transaction: tx,
account: TEST_ACCOUNT_A,
});
}
const approvalTx = setApprovalForAll({
contract: erc721TokenContract,
operator: airdropContract.address,
approved: true,
});
await sendTransaction({
transaction: approvalTx,
account: TEST_ACCOUNT_A,
});
}, 60000);
it("should send airdrop of ERC721 tokens with signature", async () => {
const contents = [
{ recipient: TEST_ACCOUNT_B.address, tokenId: 0n },
{ recipient: TEST_ACCOUNT_C.address, tokenId: 1n },
{ recipient: TEST_ACCOUNT_D.address, tokenId: 2n },
];
const { req, signature } = await generateAirdropSignatureERC721({
airdropRequest: {
tokenAddress: erc721TokenContract.address,
contents,
},
account: TEST_ACCOUNT_A,
contract: airdropContract,
});
const transaction = airdropERC721WithSignature({
contract: airdropContract,
req,
signature,
});
const { transactionHash } = await sendTransaction({
transaction,
account: TEST_ACCOUNT_A,
});
const ownerZero = await ownerOf({
contract: erc721TokenContract,
tokenId: 0n,
});
const ownerOne = await ownerOf({
contract: erc721TokenContract,
tokenId: 1n,
});
const ownerTwo = await ownerOf({
contract: erc721TokenContract,
tokenId: 2n,
});
expect(ownerZero).to.equal(TEST_ACCOUNT_B.address);
expect(ownerOne).to.equal(TEST_ACCOUNT_C.address);
expect(ownerTwo).to.equal(TEST_ACCOUNT_D.address);
expect(transactionHash.length).toBe(66);
});
},
);
@@ -0,0 +1,140 @@
import type { AbiParameterToPrimitiveType, Address } from "abitype";
import type { ThirdwebContract } from "../../../contract/contract.js";
import { dateToSeconds, tenYearsFromNow } from "../../../utils/date.js";
import type { Hex } from "../../../utils/encoding/hex.js";
import { randomBytes32 } from "../../../utils/uuid.js";
import type { Account } from "../../../wallets/interfaces/wallet.js";
import { airdropERC721WithSignature as generatedAirdropERC721WithSignature } from "../__generated__/Airdrop/write/airdropERC721WithSignature.js";
/**
* Airdrops ERC721 tokens to a list of recipients, with the request signed by admin
* @param options - The transaction options.
* @example
* ```ts
* import { airdropERC721WithSignature, generateAirdropSignatureERC721 } from "thirdweb/extensions/airdrop";
*
* const { req, signature } = await generateAirdropSignatureERC721(...)
*
* const transaction = airdropERC721WithSignature({
* contract,
* req,
* signature,
* });
* await sendTransaction({ transaction, account });
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export const airdropERC721WithSignature = generatedAirdropERC721WithSignature;
export type GenerateAirdropSignatureOptions = {
account: Account;
contract: ThirdwebContract;
airdropRequest: GenerateReqInput;
};
/**
* Generates the req and signature for sending ERC721 airdrop.
* @param options - The options for the airdrop.
* @example
* ```ts
* import { airdropERC721WithSignature, generateAirdropSignatureERC721 } from "thirdweb/extensions/airdrop";
*
* // list of recipients and tokenIds to airdrop for each recipient
* const contents = [
* { recipient: "0x...", tokenId: 0 },
* { recipient: "0x...", tokenId: 1 },
* { recipient: "0x...", tokenId: 2 },
* ];
*
* const { req, signature } = await generateAirdropSignatureERC721({
* account,
* contract,
* airdropRequest: {
* tokenAddress: "0x...", // address of the ERC721 token to airdrop
* contents
* },
* });
*
* const transaction = airdropERC721WithSignature({
* contract,
* req,
* signature,
* });
* await sendTransaction({ transaction, account });
* ```
* @extension Airdrop
* @returns A promise that resolves to the req and signature.
*/
export async function generateAirdropSignatureERC721(
options: GenerateAirdropSignatureOptions,
) {
const { airdropRequest, account, contract } = options;
const tokenAddress = airdropRequest.tokenAddress;
const contents = airdropRequest.contents;
const uid = airdropRequest.uid || (await randomBytes32());
const endTime = airdropRequest.expirationTimestamp || tenYearsFromNow();
const req: ReqType = {
uid,
tokenAddress,
expirationTimestamp: dateToSeconds(endTime),
contents,
};
const signature = await account.signTypedData({
domain: {
name: "Airdrop",
version: "1",
chainId: contract.chain.id,
verifyingContract: contract.address as Hex,
},
types: { AirdropRequestERC721, AirdropContentERC721 },
primaryType: "AirdropRequestERC721",
message: req,
});
return { req, signature };
}
type ContentType = AbiParameterToPrimitiveType<{
type: "tuple[]";
name: "contents";
components: typeof AirdropContentERC721;
}>;
type ReqType = AbiParameterToPrimitiveType<{
type: "tuple";
name: "req";
components: [
{ name: "uid"; type: "bytes32"; internalType: "bytes32" },
{ name: "tokenAddress"; type: "address"; internalType: "address" },
{ name: "expirationTimestamp"; type: "uint256"; internalType: "uint256" },
{
name: "contents";
type: "tuple[]";
components: [
{ name: "recipient"; type: "address"; internalType: "address" },
{ name: "tokenId"; type: "uint256"; internalType: "uint256" },
];
},
];
}>;
type GenerateReqInput = {
uid?: Hex;
tokenAddress: Address;
expirationTimestamp?: Date;
contents: ContentType;
};
export const AirdropContentERC721 = [
{ name: "recipient", type: "address" },
{ name: "tokenId", type: "uint256" },
] as const;
export const AirdropRequestERC721 = [
{ name: "uid", type: "bytes32" },
{ name: "tokenAddress", type: "address" },
{ name: "expirationTimestamp", type: "uint256" },
{ name: "contents", type: "AirdropContentERC721[]" },
] as const;
@@ -0,0 +1,152 @@
import { beforeAll, describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_A,
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../../test/src/test-wallets.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import {
balanceOf,
setApprovalForAll,
} from "../../../exports/extensions/erc1155.js";
import { sendTransaction } from "../../../transaction/actions/send-transaction.js";
import { mintTo } from "../../erc1155/write/mintTo.js";
import { deployERC1155Contract } from "../../prebuilts/deploy-erc1155.js";
import { deployPublishedContract } from "../../prebuilts/deploy-published.js";
import { setMerkleRoot } from "../__generated__/Airdrop/write/setMerkleRoot.js";
import { claimERC1155 } from "./claimERC1155.js";
import { generateMerkleTreeInfoERC1155 } from "./merkleInfoERC1155.js";
import { saveSnapshot } from "./saveSnapshot.js";
// skip this test suite if there is no secret key available to test with
// TODO: remove reliance on secret key during unit tests entirely
describe.runIf(process.env.TW_SECRET_KEY)("claimERC1155", () => {
let airdropContract: ThirdwebContract;
let erc1155TokenContract: ThirdwebContract;
beforeAll(async () => {
airdropContract = getContract({
address: await deployPublishedContract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
contractId: "Airdrop",
publisher: "0xFD78F7E2dF2B8c3D5bff0413c96f3237500898B3",
contractParams: [TEST_ACCOUNT_A.address, ""],
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
erc1155TokenContract = getContract({
address: await deployERC1155Contract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
params: {
name: "Test",
symbol: "TST",
},
type: "TokenERC1155",
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
const mintTransactions = [
mintTo({
contract: erc1155TokenContract,
to: TEST_ACCOUNT_A.address,
supply: 100000n,
nft: {
name: "Test 0",
},
}),
mintTo({
contract: erc1155TokenContract,
to: TEST_ACCOUNT_A.address,
supply: 100000n,
nft: {
name: "Test 1",
},
}),
];
for (const tx of mintTransactions) {
await sendTransaction({
transaction: tx,
account: TEST_ACCOUNT_A,
});
}
const approvalTx = setApprovalForAll({
contract: erc1155TokenContract,
operator: airdropContract.address,
approved: true,
});
await sendTransaction({
transaction: approvalTx,
account: TEST_ACCOUNT_A,
});
}, 60000);
it("should send ERC1155 tokens to allowlisted claimer", async () => {
const snapshot = [
{ recipient: TEST_ACCOUNT_B.address, tokenId: 0, amount: 10 },
{ recipient: TEST_ACCOUNT_C.address, tokenId: 0, amount: 12 },
{ recipient: TEST_ACCOUNT_D.address, tokenId: 1, amount: 5 },
];
const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC1155({
snapshot,
tokenAddress: erc1155TokenContract.address,
contract: airdropContract,
});
const saveSnapshotTransaction = saveSnapshot({
merkleRoot,
snapshotUri,
contract: airdropContract,
});
await sendTransaction({
transaction: saveSnapshotTransaction,
account: TEST_ACCOUNT_A,
});
const setMerkleRootTransaction = setMerkleRoot({
token: erc1155TokenContract.address,
tokenMerkleRoot: merkleRoot as `0x${string}`,
resetClaimStatus: true,
contract: airdropContract,
});
await sendTransaction({
transaction: setMerkleRootTransaction,
account: TEST_ACCOUNT_A,
});
const claimTransaction = claimERC1155({
tokenAddress: erc1155TokenContract.address,
recipient: TEST_ACCOUNT_B.address,
contract: airdropContract,
});
const { transactionHash } = await sendTransaction({
transaction: claimTransaction,
account: TEST_ACCOUNT_A,
});
const balanceB = await balanceOf({
contract: erc1155TokenContract,
owner: TEST_ACCOUNT_B.address,
tokenId: 0n,
});
expect(balanceB).to.equal(10n);
expect(transactionHash.length).toBe(66);
});
});
@@ -0,0 +1,66 @@
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import type { Address } from "../../../utils/address.js";
import { fetchProofsERC1155 } from "../../../utils/extensions/airdrop/fetch-proofs-erc1155.js";
import { tokenMerkleRoot } from "../__generated__/Airdrop/read/tokenMerkleRoot.js";
import { claimERC1155 as generatedClaimERC1155 } from "../__generated__/Airdrop/write/claimERC1155.js";
export type ClaimERC1155Params = {
tokenAddress: string;
recipient: string;
};
/**
* Claim airdrop of ERC1155 tokens for allowlisted addresses. (Pull based airdrop)
* @param options - The transaction options.
* @example
* ```ts
* import { claimERC1155 } from "thirdweb/extensions/airdrop";
*
* const tokenAddress = "0x..." // Address of airdropped tokens to claim
* const recipient = "0x..." // Address of the allowlisted recipient
*
* const claimTransaction = claimERC1155({
* contract,
* tokenAddress,
* recipient
* });
*
* await sendTransaction({ claimTransaction, account });
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export function claimERC1155(
options: BaseTransactionOptions<ClaimERC1155Params>,
) {
return generatedClaimERC1155({
contract: options.contract,
asyncParams: async () => {
const merkleRoot = await tokenMerkleRoot({
contract: options.contract,
tokenAddress: options.tokenAddress,
});
const tokenAddress = options.tokenAddress;
const merkleProof = await fetchProofsERC1155({
contract: options.contract,
recipient: options.recipient,
merkleRoot,
});
if (!merkleProof) {
throw new Error("Proof not found for recipient address");
}
return {
token: tokenAddress as Address,
receiver: merkleProof.recipient as Address,
tokenId: merkleProof.tokenId,
quantity: merkleProof.quantity,
proofs: merkleProof.proof,
} as const;
},
});
}
@@ -0,0 +1,134 @@
import { beforeAll, describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_A,
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../../test/src/test-wallets.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import { sendTransaction } from "../../../transaction/actions/send-transaction.js";
import { getBalance } from "../../erc20/read/getBalance.js";
import { approve } from "../../erc20/write/approve.js";
import { mintTo } from "../../erc20/write/mintTo.js";
import { deployERC20Contract } from "../../prebuilts/deploy-erc20.js";
import { deployPublishedContract } from "../../prebuilts/deploy-published.js";
import { setMerkleRoot } from "../__generated__/Airdrop/write/setMerkleRoot.js";
import { claimERC20 } from "./claimERC20.js";
import { generateMerkleTreeInfoERC20 } from "./merkleInfoERC20.js";
import { saveSnapshot } from "./saveSnapshot.js";
// skip this test suite if there is no secret key available to test with
// TODO: remove reliance on secret key during unit tests entirely
describe.runIf(process.env.TW_SECRET_KEY)("claimERC20", () => {
let airdropContract: ThirdwebContract;
let erc20TokenContract: ThirdwebContract;
beforeAll(async () => {
airdropContract = getContract({
address: await deployPublishedContract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
contractId: "Airdrop",
publisher: "0xFD78F7E2dF2B8c3D5bff0413c96f3237500898B3",
contractParams: [TEST_ACCOUNT_A.address, ""],
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
erc20TokenContract = getContract({
address: await deployERC20Contract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
params: {
name: "TestToken",
symbol: "TSTT",
},
type: "TokenERC20",
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
const mintTx = mintTo({
contract: erc20TokenContract,
to: TEST_ACCOUNT_A.address,
amount: 1000,
});
await sendTransaction({
transaction: mintTx,
account: TEST_ACCOUNT_A,
});
const approvalTx = await approve({
contract: erc20TokenContract,
spender: airdropContract.address,
amount: 1000,
});
await sendTransaction({
transaction: approvalTx,
account: TEST_ACCOUNT_A,
});
}, 60000);
it("should send ERC20 tokens to allowlisted claimer", async () => {
const snapshot = [
{ recipient: TEST_ACCOUNT_B.address, amount: 10 },
{ recipient: TEST_ACCOUNT_C.address, amount: 15 },
{ recipient: TEST_ACCOUNT_D.address, amount: 20 },
];
const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC20({
snapshot,
tokenAddress: erc20TokenContract.address,
contract: airdropContract,
});
const saveSnapshotTransaction = saveSnapshot({
merkleRoot,
snapshotUri,
contract: airdropContract,
});
await sendTransaction({
transaction: saveSnapshotTransaction,
account: TEST_ACCOUNT_A,
});
const setMerkleRootTransaction = setMerkleRoot({
token: erc20TokenContract.address,
tokenMerkleRoot: merkleRoot as `0x${string}`,
resetClaimStatus: true,
contract: airdropContract,
});
await sendTransaction({
transaction: setMerkleRootTransaction,
account: TEST_ACCOUNT_A,
});
const claimTransaction = claimERC20({
tokenAddress: erc20TokenContract.address,
recipient: TEST_ACCOUNT_B.address,
contract: airdropContract,
});
const { transactionHash } = await sendTransaction({
transaction: claimTransaction,
account: TEST_ACCOUNT_A,
});
const balanceB = (
await getBalance({
contract: erc20TokenContract,
address: TEST_ACCOUNT_B.address,
})
).value;
expect(balanceB).to.equal(10n * 10n ** 18n);
expect(transactionHash.length).toBe(66);
});
});
@@ -0,0 +1,88 @@
import {
ADDRESS_ZERO,
isNativeTokenAddress,
} from "../../../constants/addresses.js";
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import type { Address } from "../../../utils/address.js";
import { fetchProofsrERC20 } from "../../../utils/extensions/airdrop/fetch-proofs-erc20.js";
import { tokenMerkleRoot } from "../__generated__/Airdrop/read/tokenMerkleRoot.js";
import { claimERC20 as generatedClaimERC20 } from "../__generated__/Airdrop/write/claimERC20.js";
export type ClaimERC20Params = {
tokenAddress: string;
recipient: string;
};
/**
* Claim airdrop of ERC20 tokens for allowlisted addresses. (Pull based airdrop)
* @param options - The transaction options.
* @example
* ```ts
* import { claimERC20 } from "thirdweb/extensions/airdrop";
*
* const tokenAddress = "0x..." // Address of airdropped tokens to claim
* const recipient = "0x..." // Address of the allowlisted recipient
*
* const claimTransaction = claimERC20({
* contract,
* tokenAddress,
* recipient
* });
*
* await sendTransaction({ claimTransaction, account });
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export function claimERC20(options: BaseTransactionOptions<ClaimERC20Params>) {
return generatedClaimERC20({
contract: options.contract,
asyncParams: async () => {
const merkleRoot = await tokenMerkleRoot({
contract: options.contract,
tokenAddress: options.tokenAddress,
});
const tokenAddress = options.tokenAddress;
const tokenDecimals = await (async () => {
if (
isNativeTokenAddress(tokenAddress) ||
tokenAddress === ADDRESS_ZERO
) {
throw new Error(
"Token address can't be zero address or native token",
);
}
const [{ getContract }, { decimals: getDecimals }] = await Promise.all([
import("../../../contract/contract.js"),
import("../../erc20/read/decimals.js"),
]);
const tokenContract = getContract({
address: tokenAddress,
chain: options.contract.chain,
client: options.contract.client,
});
return await getDecimals({ contract: tokenContract });
})();
const merkleProof = await fetchProofsrERC20({
contract: options.contract,
recipient: options.recipient,
merkleRoot,
tokenDecimals,
});
if (!merkleProof) {
throw new Error("Proof not found for recipient address");
}
return {
token: tokenAddress as Address,
receiver: merkleProof.recipient as Address,
quantity: merkleProof.quantity,
proofs: merkleProof.proof,
} as const;
},
});
}
@@ -0,0 +1,163 @@
import { beforeAll, describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_A,
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../../test/src/test-wallets.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import {
ownerOf,
setApprovalForAll,
} from "../../../exports/extensions/erc721.js";
import { sendTransaction } from "../../../transaction/actions/send-transaction.js";
import { mintTo } from "../../erc721/write/mintTo.js";
import { deployERC721Contract } from "../../prebuilts/deploy-erc721.js";
import { deployPublishedContract } from "../../prebuilts/deploy-published.js";
import { setMerkleRoot } from "../__generated__/Airdrop/write/setMerkleRoot.js";
import { claimERC721 } from "./claimERC721.js";
import { generateMerkleTreeInfoERC721 } from "./merkleInfoERC721.js";
import { saveSnapshot } from "./saveSnapshot.js";
// skip this test suite if there is no secret key available to test with
// TODO: remove reliance on secret key during unit tests entirely
describe.runIf(process.env.TW_SECRET_KEY)("claimERC721", () => {
let airdropContract: ThirdwebContract;
let erc721TokenContract: ThirdwebContract;
beforeAll(async () => {
airdropContract = getContract({
address: await deployPublishedContract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
contractId: "Airdrop",
publisher: "0xFD78F7E2dF2B8c3D5bff0413c96f3237500898B3",
contractParams: [TEST_ACCOUNT_A.address, ""],
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
erc721TokenContract = getContract({
address: await deployERC721Contract({
account: TEST_ACCOUNT_A,
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
params: {
name: "Test",
symbol: "TST",
},
type: "TokenERC721",
}),
chain: ANVIL_CHAIN,
client: TEST_CLIENT,
});
const mintTransactions = [
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 0",
},
}),
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 1",
},
}),
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 2",
},
}),
mintTo({
contract: erc721TokenContract,
to: TEST_ACCOUNT_A.address,
nft: {
name: "Test 3",
},
}),
];
for (const tx of mintTransactions) {
await sendTransaction({
transaction: tx,
account: TEST_ACCOUNT_A,
});
}
const approvalTx = setApprovalForAll({
contract: erc721TokenContract,
operator: airdropContract.address,
approved: true,
});
await sendTransaction({
transaction: approvalTx,
account: TEST_ACCOUNT_A,
});
}, 60000);
it("should send ERC721 tokens to allowlisted claimer", async () => {
const snapshot = [
{ recipient: TEST_ACCOUNT_B.address, tokenId: 0 },
{ recipient: TEST_ACCOUNT_C.address, tokenId: 1 },
{ recipient: TEST_ACCOUNT_D.address, tokenId: 2 },
];
const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC721({
snapshot,
tokenAddress: erc721TokenContract.address,
contract: airdropContract,
});
const saveSnapshotTransaction = saveSnapshot({
merkleRoot,
snapshotUri,
contract: airdropContract,
});
await sendTransaction({
transaction: saveSnapshotTransaction,
account: TEST_ACCOUNT_A,
});
const setMerkleRootTransaction = setMerkleRoot({
token: erc721TokenContract.address,
tokenMerkleRoot: merkleRoot as `0x${string}`,
resetClaimStatus: true,
contract: airdropContract,
});
await sendTransaction({
transaction: setMerkleRootTransaction,
account: TEST_ACCOUNT_A,
});
const claimTransaction = claimERC721({
tokenAddress: erc721TokenContract.address,
recipient: TEST_ACCOUNT_B.address,
contract: airdropContract,
});
const { transactionHash } = await sendTransaction({
transaction: claimTransaction,
account: TEST_ACCOUNT_A,
});
const ownerZero = await ownerOf({
contract: erc721TokenContract,
tokenId: 0n,
});
expect(ownerZero).to.equal(TEST_ACCOUNT_B.address);
expect(transactionHash.length).toBe(66);
});
});
@@ -0,0 +1,65 @@
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import type { Address } from "../../../utils/address.js";
import { fetchProofsERC721 } from "../../../utils/extensions/airdrop/fetch-proofs-erc721.js";
import { tokenMerkleRoot } from "../__generated__/Airdrop/read/tokenMerkleRoot.js";
import { claimERC721 as generatedClaimERC721 } from "../__generated__/Airdrop/write/claimERC721.js";
export type ClaimERC721Params = {
tokenAddress: string;
recipient: string;
};
/**
* Claim airdrop of ERC721 tokens for allowlisted addresses. (Pull based airdrop)
* @param options - The transaction options.
* @example
* ```ts
* import { claimERC721 } from "thirdweb/extensions/airdrop";
*
* const tokenAddress = "0x..." // Address of airdropped tokens to claim
* const recipient = "0x..." // Address of the allowlisted recipient
*
* const claimTransaction = claimERC721({
* contract,
* tokenAddress,
* recipient
* });
*
* await sendTransaction({ claimTransaction, account });
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export function claimERC721(
options: BaseTransactionOptions<ClaimERC721Params>,
) {
return generatedClaimERC721({
contract: options.contract,
asyncParams: async () => {
const merkleRoot = await tokenMerkleRoot({
contract: options.contract,
tokenAddress: options.tokenAddress,
});
const tokenAddress = options.tokenAddress;
const merkleProof = await fetchProofsERC721({
contract: options.contract,
recipient: options.recipient,
merkleRoot,
});
if (!merkleProof) {
throw new Error("Proof not found for recipient address");
}
return {
token: tokenAddress as Address,
receiver: merkleProof.recipient as Address,
tokenId: merkleProof.tokenId,
proofs: merkleProof.proof,
} as const;
},
});
}
@@ -0,0 +1,54 @@
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { processSnapshotERC1155 } from "../../../utils/extensions/airdrop/process-snapshot-erc1155.js";
import type { SnapshotEntryERC1155 } from "../../../utils/extensions/airdrop/types.js";
export type GenerateMerkleTreeInfoParams = {
snapshot: SnapshotEntryERC1155[];
tokenAddress: string;
};
/**
* Generate merkle tree for a given snapshot.
* @param options - The transaction options.
* @example
* ```ts
* import { generateMerkleTreeInfoERC1155 } from "thirdweb/extensions/airdrop";
*
* // snapshot / allowlist of airdrop recipients and amounts
* const snapshot = [
* { recipient: "0x...", tokenId: 0, amount: 10 },
* { recipient: "0x...", tokenId: 1, amount: 12 },
* { recipient: "0x...", tokenId: 2, amount: 15 },
* ];
*
* const tokenAddress = "0x..." // Address of ERC1155 airdrop token
*
* const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC1155({
* contract,
* tokenAddress,
* snapshot
* });
*
* // Optional next steps {See: saveSnapshot and setMerkleRoot functions}
* // - Save snapshot on-chain (on the airdrop contract uri)
* // - Set merkle root on the contract to enable claiming
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the merkle-root and snapshot-uri.
*/
export async function generateMerkleTreeInfoERC1155(
options: BaseTransactionOptions<GenerateMerkleTreeInfoParams>,
) {
const { snapshot, contract } = options;
// generate merkle tree from snapshot
const { shardedMerkleInfo, uri } = await processSnapshotERC1155({
snapshot,
client: contract.client,
});
return {
merkleRoot: shardedMerkleInfo.merkleRoot,
snapshotUri: uri,
};
}
@@ -0,0 +1,77 @@
import {
ADDRESS_ZERO,
isNativeTokenAddress,
} from "../../../constants/addresses.js";
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { processSnapshotERC20 } from "../../../utils/extensions/airdrop/process-snapshot-erc20.js";
import type { SnapshotEntryERC20 } from "../../../utils/extensions/airdrop/types.js";
export type GenerateMerkleTreeInfoParams = {
snapshot: SnapshotEntryERC20[];
tokenAddress: string;
};
/**
* Generate merkle tree for a given snapshot.
* @param options - The transaction options.
* @example
* ```ts
* import { generateMerkleTreeInfoERC20 } from "thirdweb/extensions/airdrop";
*
* // snapshot / allowlist of airdrop recipients and amounts
* const snapshot = [
* { recipient: "0x...", amount: 10 },
* { recipient: "0x...", amount: 15 },
* { recipient: "0x...", amount: 20 },
* ];
*
* const tokenAddress = "0x..." // Address of ERC20 airdrop token
*
* const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC20({
* contract,
* tokenAddress,
* snapshot
* });
*
* // Optional next steps {See: saveSnapshot and setMerkleRoot functions}
* // - Save snapshot on-chain (on the airdrop contract uri)
* // - Set merkle root on the contract to enable claiming
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the merkle-root and snapshot-uri.
*/
export async function generateMerkleTreeInfoERC20(
options: BaseTransactionOptions<GenerateMerkleTreeInfoParams>,
) {
const { snapshot, contract } = options;
// get token decimals
const tokenAddress = options.tokenAddress;
const tokenDecimals = await (async () => {
if (isNativeTokenAddress(tokenAddress) || tokenAddress === ADDRESS_ZERO) {
throw new Error("Token address can't be zero address or native token");
}
const [{ getContract }, { decimals: getDecimals }] = await Promise.all([
import("../../../contract/contract.js"),
import("../../erc20/read/decimals.js"),
]);
const tokenContract = getContract({
address: tokenAddress,
chain: contract.chain,
client: contract.client,
});
return await getDecimals({ contract: tokenContract });
})();
// generate merkle tree from snapshot
const { shardedMerkleInfo, uri } = await processSnapshotERC20({
snapshot,
client: contract.client,
tokenDecimals,
});
return {
merkleRoot: shardedMerkleInfo.merkleRoot,
snapshotUri: uri,
};
}
@@ -0,0 +1,54 @@
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { processSnapshotERC721 } from "../../../utils/extensions/airdrop/process-snapshot-erc721.js";
import type { SnapshotEntryERC721 } from "../../../utils/extensions/airdrop/types.js";
export type GenerateMerkleTreeInfoParams = {
snapshot: SnapshotEntryERC721[];
tokenAddress: string;
};
/**
* Generate merkle tree for a given snapshot.
* @param options - The transaction options.
* @example
* ```ts
* import { generateMerkleTreeInfoERC721 } from "thirdweb/extensions/airdrop";
*
* // snapshot / allowlist of airdrop recipients and amounts
* const snapshot = [
* { recipient: "0x...", tokenId: 0 },
* { recipient: "0x...", tokenId: 1 },
* { recipient: "0x...", tokenId: 2 },
* ];
*
* const tokenAddress = "0x..." // Address of ERC721 airdrop token
*
* const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC721({
* contract,
* tokenAddress,
* snapshot
* });
*
* // Optional next steps {See: saveSnapshot and setMerkleRoot functions}
* // - Save snapshot on-chain (on the airdrop contract uri)
* // - Set merkle root on the contract to enable claiming
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the merkle-root and snapshot-uri.
*/
export async function generateMerkleTreeInfoERC721(
options: BaseTransactionOptions<GenerateMerkleTreeInfoParams>,
) {
const { snapshot, contract } = options;
// generate merkle tree from snapshot
const { shardedMerkleInfo, uri } = await processSnapshotERC721({
snapshot,
client: contract.client,
});
return {
merkleRoot: shardedMerkleInfo.merkleRoot,
snapshotUri: uri,
};
}
@@ -0,0 +1,101 @@
import { upload } from "../../../storage/upload.js";
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { setContractURI } from "../__generated__/Airdrop/write/setContractURI.js";
export type SaveSnapshotParams = {
merkleRoot: string;
snapshotUri: string;
};
/**
* Generate merkle tree for a given snapshot and save the info on-chain.
* @param options - The transaction options.
* @example
* ```ts
*
* // This is ERC20 example. Should import and use other ERC variants as needed
*
* import { generateMerkleTreeInfoERC20, saveSnapshot, setMerkleRoot } from "thirdweb/extensions/airdrop";
*
* // snapshot / allowlist of airdrop recipients and amounts
* const snapshot = [
* { recipient: "0x...", amount: 10 },
* { recipient: "0x...", amount: 15 },
* { recipient: "0x...", amount: 20 },
* ];
*
* const tokenAddress = "0x..." // Address of airdrop token
*
* const { merkleRoot, snapshotUri } = await generateMerkleTreeInfoERC20({
* contract,
* tokenAddress,
* snapshot
* });
*
* const saveSnapshotTransaction = saveSnapshot({
* contract,
* merkleRoot,
* snapshotUri,
* });
* await sendTransaction({ saveSnapshotTransaction, account });
*
* const setMerkleRootTransaction = setMerkleRoot({
* contract,
* token,
* tokenMerkleRoot: merkleRoot as `0x${string}`,
* resetClaimStatus: false // toggle as needed
* signature,
* });
* await sendTransaction({ setMerkleRootTransaction, account });
*
* ```
* @extension Airdrop
* @returns A promise that resolves to the transaction result.
*/
export function saveSnapshot(
options: BaseTransactionOptions<SaveSnapshotParams>,
) {
return setContractURI({
contract: options.contract,
asyncParams: async () => {
const merkleInfos: Record<string, string> = {};
// need to upload merkle tree info to the contract metadata
const [{ getContractMetadata }, { contractURI }] = await Promise.all([
import("../../common/read/getContractMetadata.js"),
import(
"../../common/__generated__/IContractMetadata/read/contractURI.js"
),
]);
const metadata = await getContractMetadata({
contract: options.contract,
});
const contractUri = await contractURI({
contract: options.contract,
});
merkleInfos[options.merkleRoot] = options.snapshotUri;
// keep the old merkle roots from other tokenIds
for (const key of Object.keys(metadata.merkle || {})) {
merkleInfos[key] = metadata.merkle[key];
}
const mergedMetadata = {
...metadata,
merkle: merkleInfos,
};
const uri = await upload({
client: options.contract.client,
files: [mergedMetadata],
});
if (uri === contractUri) {
throw new Error("Merkle tree info already saved");
}
return {
uri,
} as const;
},
});
}
@@ -18,7 +18,7 @@ export type SetClaimConditionsParams = {
* ```ts
* import { setClaimConditions } from "thirdweb/extensions/erc1155";
*
* const tx = await setClaimConditions({
* const tx = setClaimConditions({
* contract,
* tokenId: 0n,
* phases: [
@@ -1,14 +1,21 @@
import type { AbiParameterToPrimitiveType, Address } from "abitype";
import { maxUint256 } from "viem";
import { NATIVE_TOKEN_ADDRESS } from "../../../constants/addresses.js";
import {
NATIVE_TOKEN_ADDRESS,
isNativeTokenAddress,
} from "../../../constants/addresses.js";
import type { ThirdwebContract } from "../../../contract/contract.js";
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { toBigInt } from "../../../utils/bigint.js";
import { dateToSeconds, tenYearsFromNow } from "../../../utils/date.js";
import type { Hex } from "../../../utils/encoding/hex.js";
import type { NFTInput } from "../../../utils/nft/parseNft.js";
import { randomBytes32 } from "../../../utils/uuid.js";
import type { Account } from "../../../wallets/interfaces/wallet.js";
import { mintWithSignature as generatedMintWithSignature } from "../__generated__/ISignatureMintERC1155/write/mintWithSignature.js";
import {
type MintWithSignatureParams,
mintWithSignature as generatedMintWithSignature,
} from "../__generated__/ISignatureMintERC1155/write/mintWithSignature.js";
/**
* Mints a new ERC1155 token with the given minter signature
@@ -29,7 +36,19 @@ import { mintWithSignature as generatedMintWithSignature } from "../__generated_
* @extension ERC1155
* @returns A promise that resolves to the transaction result.
*/
export const mintWithSignature = generatedMintWithSignature;
export function mintWithSignature(
options: BaseTransactionOptions<MintWithSignatureParams>,
) {
const value = isNativeTokenAddress(options.payload.currency)
? options.payload.pricePerToken * options.payload.quantity
: 0n;
return generatedMintWithSignature({
...options,
overrides: {
value,
},
});
}
export type GenerateMintSignatureOptions = {
account: Account;

Some files were not shown because too many files have changed in this diff Show More