Skip to content
This repository was archived by the owner on Jan 2, 2024. It is now read-only.

Commit c0fea4a

Browse files
committed
Added HashLips conversion and IPFS upload
1 parent 41aecc5 commit c0fea4a

File tree

5 files changed

+4170
-101
lines changed

5 files changed

+4170
-101
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ cache
88
.DS_Store
99
.idea
1010
.cache
11+
hashlips-output

README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,19 @@ We recommend you first execute this against a locally running Algorand sandbox n
2727

2828
### Regardless of whether minting against local Algorand emulator or not
2929

30-
1. Open in VS Code (or your IDE of choice, although you'll get a better developer experience in VS Code since there are run and debug configurations and settings specified)
31-
2. Install recommended extensions
32-
3. Inside `minter`:
30+
1. Run your HashLips generator and copy the output from the `build` folder into the `hashlips-output` folder in this repository - that should result in a `hashlips-output/images` and `hashlips-output/json` folder
31+
2. Open in VS Code (or your IDE of choice, although you'll get a better developer experience in VS Code since there are run and debug configurations and settings specified)
32+
3. Install recommended extensions
33+
4. Inside `minter`:
3334

3435
- Copy `.env.sample` to `.env` and fill in the relevant variables, including Web3.Storage token and, depending on whether you want to test against either the local sandbox or Algorand TestNet, the Algorand node config (e.g. via [AlgoNode](https://algonode.io/api/) or via [PureStake](https://purestake.io/), for which you would need to [create an account](https://developer.purestake.io/signup))
3536
- Run `npm install`
3637

37-
4. Add the metadata for your particular NFT project in `minter/index.ts`
38+
5. Add the metadata for your particular NFT project in `minter/index.ts` (look for `NFT metadata - edit this`)
3839

39-
5. (If using VS Code) Choose the thing you want to run/debug from the "Run and Debug" pane (ctrl+shift+D on Windows) and hit F5 and it will launch it with breakpoint debugging
40+
6. (If using VS Code) Choose the thing you want to run/debug from the "Run and Debug" pane (ctrl+shift+D on Windows) and hit F5 and it will launch it with breakpoint debugging
4041

41-
6. OR (If not using VS Code) run `npm run dev` in the `minter` folder
42+
7. OR (If not using VS Code) run `npm run dev` in the `minter` folder
4243

4344
## Ongoing development
4445

minter/index.ts

+56-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { Account, Algodv2 } from 'algosdk'
2-
import fs from 'fs'
2+
import fsSync from 'fs'
3+
import fs from 'fs/promises'
4+
import path from 'path'
5+
import { getFilesFromPath, Web3Storage } from 'web3.storage'
36
import { CREATOR_ACCOUNT } from './constants'
47
import { getAccount } from './functions/account'
58
import { chunkArray } from './functions/array'
@@ -18,22 +21,47 @@ const mediaType = MediaType.Image
1821
/**** End of NFT metadata ******/
1922
/*********************************/
2023

21-
if (!fs.existsSync('.env') && !process.env.ALGOD_SERVER) {
22-
console.error('Copy .env.sample to .env before starting the application.')
24+
if (!fsSync.existsSync('.env') && (!process.env.ALGOD_SERVER || !process.env.WEB3_STORAGE_API_TOKEN)) {
25+
console.error('Copy .env.sample to .env and fill in before starting the application.')
2326
process.exit(1)
2427
}
2528
;(async () => {
2629
try {
2730
const client = await getAlgoClient()
31+
const storage = new Web3Storage({ token: process.env.WEB3_STORAGE_API_TOKEN! })
2832
const creatorAccount = await getAccount(client, CREATOR_ACCOUNT)
2933

30-
// todo: Get HashLips metadata
31-
const project = {
32-
name: 'PROJECT',
33-
}
34+
// Upload images to IPFS
35+
const cid = await uploadToIPFS(storage, '../hashlips-output/images/')
36+
37+
// Parse HashLips metadata output
3438
const nftsToMint: NFT[] = []
39+
const hashLipsOutput = await fs.readdir(path.join(__dirname, '../hashlips-output/json'))
40+
for (let metadataFile of hashLipsOutput) {
41+
if (metadataFile === '_metadata.json') {
42+
continue
43+
}
3544

36-
console.log(`Minting NFTs for ${project.name}`)
45+
const metadataJSON = await fs.readFile(path.join(__dirname, '../hashlips-output/json', metadataFile))
46+
const metadata = JSON.parse(metadataJSON.toString('utf-8')) as HashLipsMetadata
47+
48+
const traits: Record<string, string> = {}
49+
if (metadata.attributes) {
50+
metadata.attributes.forEach((a) => {
51+
traits[a.trait_type] = a.value
52+
})
53+
}
54+
55+
nftsToMint.push({
56+
dna: metadata.dna,
57+
imageUrl: metadata.image.replace('ipfs://NewUriToReplace/', `ipfs://${cid}/images/`),
58+
name: metadata.name,
59+
description: metadata.description,
60+
traits: traits,
61+
})
62+
}
63+
64+
console.log(`Found ${nftsToMint.length} HashLips generated NFTs`)
3765

3866
const accountInformation = await client.accountInformation(creatorAccount.addr).do()
3967
const existingAlgorandNFTs = (accountInformation['created-assets'] as AssetResult[]).filter(
@@ -84,6 +112,21 @@ if (!fs.existsSync('.env') && !process.env.ALGOD_SERVER) {
84112
process.exit(1)
85113
}
86114
})()
115+
interface HashLipsMetadataTrait {
116+
trait_type: string
117+
value: string
118+
}
119+
120+
interface HashLipsMetadata {
121+
compiler: string
122+
date: number
123+
description: string
124+
dna: string
125+
edition: number
126+
image: string
127+
name: string
128+
attributes: HashLipsMetadataTrait[]
129+
}
87130

88131
interface NFT {
89132
dna: string
@@ -94,6 +137,11 @@ interface NFT {
94137
traits?: Record<string, string>
95138
}
96139

140+
async function uploadToIPFS(storage: Web3Storage, filePath: string) {
141+
const fileRef = await getFilesFromPath(filePath)
142+
return await storage.put(fileRef)
143+
}
144+
97145
async function getAlgorandNFTTransaction(
98146
client: Algodv2,
99147
creatorAccount: Account,

0 commit comments

Comments
 (0)