-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9d9c103
commit 364ee38
Showing
87 changed files
with
6,442 additions
and
48 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
packages/minting-backend/minting-sample-app/backend/.env.example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#Obtained at hub.immutable.com | ||
SANDBOX_HUB_IMMUTABLE_API_KEY= | ||
SANDBOX_RPS_IMMUTABLE_API_KEY= | ||
|
||
MAINNET_HUB_IMMUTABLE_API_KEY= | ||
MAINNET_RPS_IMMUTABLE_API_KEY= | ||
|
||
# Example: file:./allowList.db | ||
DATABASE_URL= |
6 changes: 6 additions & 0 deletions
6
packages/minting-backend/minting-sample-app/backend/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.env | ||
/node_modules | ||
.DS_Store | ||
prisma/allowList.db | ||
prisma/allowList.db-journal | ||
/logs |
98 changes: 98 additions & 0 deletions
98
packages/minting-backend/minting-sample-app/backend/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Minting API Backend for conducting a free mint | ||
|
||
This project is a backend API for doing a free mint on IMX zkEVM. | ||
|
||
## Disclaimer | ||
|
||
The sample code provided is for reference purposes only. It has undergone best effort testing by Immutable to ensure basic functionality. However, it is essential that you thoroughly test this sample code within your own environment to confirm its functionality and reliability before deploying it in a production setting. Immutable disclaims any liability for any issues that arise due to the use of this sample code. By using this sample code, you agree to perform due diligence in testing and verifying its suitability for your applications. | ||
|
||
## Features | ||
|
||
- Uses the Immutable Minting API to ensure that minting is sponsored on top of transaction life cycle monitoring, nonce management etc. is abstracted. | ||
- Async Minting by 1. store minting intention, 2. submit minting to Immutable Minting API in background, 3. listening to webhook for minting status. | ||
- Passport authentication. | ||
- Define phases that the mint should occur in, start times and end times. | ||
- Ability to allowlist addresses for minting for different phases | ||
|
||
## Setup Instructions | ||
|
||
1. Install the dependencies: | ||
``` | ||
npm i | ||
``` | ||
2. Copy the example environment file and fill it with your API key, and DB path(should be `file:./allowList.db`): | ||
``` | ||
cp .env.example .env | ||
``` | ||
3. Make sure to configure `src/config.ts` with collection address etc after deploying the contract on hub.immutable.com. Pay specific attention to the mintPhases parameter: | ||
``` | ||
mintPhases: [ | ||
{ | ||
name: "Presale", | ||
startTime: 1629913600, | ||
endTime: 1629999999, | ||
maxSupply: 1000, | ||
enableAllowList: true, | ||
}, | ||
{ | ||
name: "Public Sale", | ||
startTime: 1630000000, | ||
endTime: 1719292800, | ||
maxSupply: 9000, | ||
enableAllowList: false, | ||
maxPerWallet: 2, | ||
}], | ||
``` | ||
Keep in mind that you can configure a single phase if you're not planning a phased approach but just a start/end time. | ||
|
||
This sample app only support the same metadata for all the mints. it is defined in the `metadata` field in the same `src/config.ts` file. Please make amend logic inside `server.ts` for calls to `mintingBackend.recordMint` to give metadata per token. | ||
|
||
4. Run the DB migrations: | ||
|
||
``` | ||
npx prisma migrate dev | ||
``` | ||
|
||
Every time you change primsa schema you need to run the above. | ||
|
||
5. Load your database, https://sqlitebrowser.org/ is great for this. You can also write a script that uses the Prisma client to load the database. Make sure you have your address allowlisted, and quantity is 1, isLocked is 0, hasMinted is 0. | ||
|
||
6. Run the development server: | ||
|
||
``` | ||
npm start | ||
``` | ||
|
||
7. Create your webhook at https://hub.immutable.com/, use localtunnel for testing webhooks locally: | ||
|
||
``` | ||
npx localtunnel --port 3000 | ||
``` | ||
|
||
Use the above URL for the webhook endpoint with the path `/webhook`. For example: `https://ten-rooms-vanish.loca.lt/webhook`. | ||
|
||
8. Use Postgresql instead of SQLite | ||
This example uses SQLite as database for its portability and self-contain-ness. | ||
However, ** please do not use SQLite in production ** for its weak support of concurrency. | ||
|
||
We recommend using postgres for the persistance. Immutable's sdk provides a postgres persistence for this purpose. You can replace `mintingBackend.mintingPersistencePrismaSqlite` with `mintingBackend.mintingPersistencePg` in the `server.ts` and change prisma schema according to the one provided by our sdk: [Postgres seed.sql](https://github.com/immutable/ts-immutable-sdk/blob/main/packages/minting-backend/sdk/src/minting/persistence/pg/seed.sql). | ||
|
||
## Utility | ||
|
||
Retry failed mints or mints recorded but does not exist in Immutable Minting API. | ||
|
||
``` | ||
npm run retrymints | ||
``` | ||
|
||
update minting status according to status from Immutable Minting API. | ||
|
||
``` | ||
npm run updatemints | ||
``` | ||
|
||
## To-Do List | ||
|
||
- [ ] Add ERC1155 support once the minting API is ready | ||
- [ ] Add the ability to choose whether you want mintByQuantity or mintByID | ||
- [ ] this sample app will be ported over to use postgres in the future. |
43 changes: 43 additions & 0 deletions
43
packages/minting-backend/minting-sample-app/backend/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"name": "minting-api-backend", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"start": "ts-node-dev --respawn --transpile-only src/server.ts", | ||
"updatemints": "ts-node src/utils/updateMintStatus.ts", | ||
"retrymints": "ts-node src/utils/mintFailsAndMissing.ts" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"@fastify/cors": "^9.0.1", | ||
"@imtbl/sdk": "1.34.2-alpha", | ||
"@prisma/client": "^5.12.1", | ||
"@types/jsonwebtoken": "^9.0.6", | ||
"aws-sdk": "^2.1603.0", | ||
"ethereum-cryptography": "^2.1.3", | ||
"ethers": "^6.12.1", | ||
"fastify": "^4.26.2", | ||
"jsonwebtoken": "^9.0.2", | ||
"jwk-to-pem": "^2.0.5", | ||
"prisma": "^5.12.1", | ||
"sns-validator": "^0.3.5", | ||
"util": "^0.12.5", | ||
"uuid": "^9.0.1", | ||
"viem": "^2.9.29", | ||
"winston": "^3.13.0", | ||
"winston-daily-rotate-file": "^5.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.12.7", | ||
"@types/pg": "^8.11.6", | ||
"@types/sns-validator": "^0.3.3", | ||
"@types/uuid": "^9.0.8", | ||
"artillery": "^2.0.11", | ||
"ts-node-dev": "^2.0.0", | ||
"typescript": "^5.4.5" | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...ng-backend/minting-sample-app/backend/prisma/migrations/20240514064848_init/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
-- CreateTable | ||
CREATE TABLE "im_assets" ( | ||
"id" TEXT NOT NULL PRIMARY KEY, | ||
"assetId" TEXT NOT NULL, | ||
"ownerAddress" TEXT NOT NULL, | ||
"metadata" TEXT, | ||
"tokenId" TEXT, | ||
"contractAddress" TEXT NOT NULL, | ||
"error" TEXT, | ||
"mintingStatus" TEXT, | ||
"metadataId" TEXT, | ||
"triedCount" INTEGER NOT NULL DEFAULT 0, | ||
"lastImtblZkevmMintRequestUpdatedId" TEXT, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "im_assets_assetId_contractAddress_key" ON "im_assets"("assetId", "contractAddress"); |
5 changes: 5 additions & 0 deletions
5
...ckend/minting-sample-app/backend/prisma/migrations/20240514065018_allowlist/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
-- CreateTable | ||
CREATE TABLE "Allowlist" ( | ||
"address" TEXT NOT NULL PRIMARY KEY, | ||
"phase" INTEGER NOT NULL | ||
); |
3 changes: 3 additions & 0 deletions
3
packages/minting-backend/minting-sample-app/backend/prisma/migrations/migration_lock.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Please do not edit this file manually | ||
# It should be added in your version-control system (i.e. Git) | ||
provider = "sqlite" |
38 changes: 38 additions & 0 deletions
38
packages/minting-backend/minting-sample-app/backend/prisma/schema.prisma
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// This is your Prisma schema file, | ||
// learn more about it in the docs: https://pris.ly/d/prisma-schema | ||
|
||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? | ||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init | ||
|
||
generator client { | ||
provider = "prisma-client-js" | ||
} | ||
|
||
datasource db { | ||
provider = "sqlite" | ||
url = env("DATABASE_URL") | ||
} | ||
|
||
model ImAssets { | ||
id String @id @default(uuid()) | ||
assetId String // Previously @db.Uuid in Postgres | ||
ownerAddress String | ||
metadata String? // Previously Json? @db.JsonB in Postgres | ||
tokenId String? | ||
contractAddress String | ||
error String? | ||
mintingStatus String? | ||
metadataId String? // Previously @db.Uuid in Postgres | ||
triedCount Int @default(0) | ||
lastImtblZkevmMintRequestUpdatedId String? // Previously @db.Uuid in Postgres | ||
createdAt DateTime @default(now()) // Stored as TEXT | ||
updatedAt DateTime @default(now()) // Stored as TEXT | ||
@@map("im_assets") | ||
@@unique([assetId, contractAddress], name: "im_assets_uindex") | ||
} | ||
|
||
model Allowlist { | ||
address String @id | ||
phase Int | ||
} |
10 changes: 10 additions & 0 deletions
10
packages/minting-backend/minting-sample-app/backend/src/blockchainDataClient.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import serverConfig, { environment } from "./config"; | ||
import { blockchainData } from "@imtbl/sdk"; | ||
|
||
export const blockchainDataClient = new blockchainData.BlockchainData({ | ||
baseConfig: { | ||
environment: environment, | ||
apiKey: serverConfig[environment].HUB_API_KEY, | ||
rateLimitingKey: serverConfig[environment].RPS_API_KEY, | ||
} | ||
}); |
78 changes: 78 additions & 0 deletions
78
packages/minting-backend/minting-sample-app/backend/src/config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { config } from "@imtbl/sdk"; | ||
import { ServerConfig } from "./types"; | ||
require("dotenv").config(); | ||
|
||
//config.Environment.SANDBOX or config.Environment.PRODUCTION | ||
export const environment = config.Environment.SANDBOX; | ||
|
||
//Used for verification of the Passport JWTs | ||
export const IMX_JWT_KEY_URL = "https://auth.immutable.com/.well-known/jwks.json?_gl=1*1g7a0qs*_ga*NDg1NTg3MDI3LjE2ODU1OTY1Mzg.*_ga_4JBHZ7F06X*MTY4ODUyNjkyNy4xNC4wLjE2ODg1MjY5MjcuMC4wLjA.*_ga_7XM4Y7T8YC*MTY4ODUyNjkyNy4yNy4wLjE2ODg1MjY5MjcuMC4wLjA."; | ||
|
||
const serverConfig: ServerConfig = { | ||
[config.Environment.SANDBOX]: { | ||
API_URL: "https://api.sandbox.immutable.com", | ||
HUB_API_KEY: process.env.SANDBOX_HUB_IMMUTABLE_API_KEY!, | ||
RPS_API_KEY: process.env.SANDBOX_RPS_IMMUTABLE_API_KEY!, | ||
HOST_IP: "localhost", | ||
PORT: 3000, | ||
chainName: "imtbl-zkevm-testnet", | ||
collectionAddress: "", | ||
enableFileLogging: true, //Should logs be output to files or just console? | ||
maxTokenSupplyAcrossAllPhases: 1500, | ||
logLevel: "debug", | ||
eoaMintMessage: "Sign this message to verify your wallet address", //The message an EOA signs to verify their wallet address and mint | ||
mintPhases: [ | ||
{ | ||
name: "Guaranteed", | ||
startTime: 1715743355, | ||
endTime: 1735743376, | ||
}, | ||
{ | ||
name: "Waitlist", | ||
startTime: 1714916593, | ||
endTime: 1719292800, | ||
}, | ||
], | ||
metadata: { | ||
name: "Your NFT name", | ||
description: "Your NFT description", | ||
image: "https://image-url.png", | ||
animation_url: "https://video.mp4", | ||
attributes: [], | ||
}, | ||
}, | ||
[config.Environment.PRODUCTION]: { | ||
API_URL: "https://api.immutable.com", | ||
HUB_API_KEY: process.env.MAINNET_HUB_IMMUTABLE_API_KEY!, | ||
RPS_API_KEY: process.env.MAINNET_RPS_IMMUTABLE_API_KEY!, | ||
HOST_IP: "localhost", | ||
PORT: 3000, | ||
chainName: "imtbl-zkevm-mainnet", | ||
collectionAddress: "", | ||
enableFileLogging: true, //Should logs be output to files or just console? | ||
maxTokenSupplyAcrossAllPhases: 1500, | ||
logLevel: "debug", | ||
eoaMintMessage: "Sign this message to verify your wallet address", //The message an EOA signs to verify their wallet address and mint | ||
mintPhases: [ | ||
{ | ||
name: "Guaranteed", | ||
startTime: 1629913600, | ||
endTime: 1714623711, | ||
}, | ||
{ | ||
name: "Waitlist", | ||
startTime: 1714623712, | ||
endTime: 1719292800, | ||
}, | ||
], | ||
metadata: { | ||
name: "Your NFT name", | ||
description: "Your NFT description", | ||
image: "https://image-url.png", | ||
animation_url: "https://video.mp4", | ||
attributes: [], | ||
}, | ||
}, | ||
}; | ||
|
||
export default serverConfig; |
59 changes: 59 additions & 0 deletions
59
packages/minting-backend/minting-sample-app/backend/src/database.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { PrismaClient } from "@prisma/client"; | ||
import logger from "./logger"; | ||
|
||
export async function checkAddressMinted(address: string, client: PrismaClient): Promise<string | null> { | ||
try { | ||
logger.info(`Checking if user has minted: ${address}`); | ||
const mintedAddress = await client.imAssets.findFirst({ | ||
where: { | ||
ownerAddress: address, | ||
}, | ||
}); | ||
logger.info(`User has minted: ${mintedAddress !== null}`); | ||
return mintedAddress?.assetId ?? null; | ||
} catch (error) { | ||
logger.error(`Error checking if user has minted: ${error}`); | ||
throw error; | ||
} | ||
} | ||
|
||
export async function totalMintCountAcrossAllPhases(client: PrismaClient): Promise<number> { | ||
try { | ||
const mintCount = await client.imAssets.count(); | ||
return mintCount; | ||
} catch (error) { | ||
logger.error(`Error getting total mint count: ${error}`); | ||
throw error; | ||
} | ||
} | ||
|
||
|
||
export async function loadAddressesIntoAllowlist(addresses: string[], phase: number, client: PrismaClient) { | ||
try { | ||
for (let address of addresses) { | ||
await client.allowlist.create({ | ||
data: { | ||
address: address.toLowerCase(), | ||
phase: phase, | ||
}, | ||
}); | ||
} | ||
console.log("Addresses have been successfully loaded into the database."); | ||
} catch (error) { | ||
console.error("Error loading addresses into the database:", error); | ||
} | ||
} | ||
|
||
export async function readAddressesFromAllowlist(phase: number, client: PrismaClient): Promise<string[]> { | ||
try { | ||
const addresses = await client.allowlist.findMany({ | ||
where: { | ||
phase: phase, | ||
}, | ||
}); | ||
return addresses.map((address: any) => address.address.toLowerCase()); | ||
} catch (error) { | ||
console.error("Error reading addresses from the database:", error); | ||
throw error; | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/minting-backend/minting-sample-app/backend/src/dbClient.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { PrismaClient } from '@prisma/client'; | ||
|
||
const client = new PrismaClient(); | ||
|
||
export { client }; |
Oops, something went wrong.