diff --git a/.changeset/light-boats-relate.md b/.changeset/light-boats-relate.md
new file mode 100644
index 00000000..afa013ec
--- /dev/null
+++ b/.changeset/light-boats-relate.md
@@ -0,0 +1,5 @@
+---
+'freshmint': minor
+---
+
+Show claim transaction status in web UI
diff --git a/.changeset/sixty-kings-vanish.md b/.changeset/sixty-kings-vanish.md
new file mode 100644
index 00000000..fab355e4
--- /dev/null
+++ b/.changeset/sixty-kings-vanish.md
@@ -0,0 +1,5 @@
+---
+'@freshmint/cadence-loader': minor
+---
+
+Inject environment variables into cadence-loader
diff --git a/.changeset/three-peas-live.md b/.changeset/three-peas-live.md
new file mode 100644
index 00000000..e5bde2e4
--- /dev/null
+++ b/.changeset/three-peas-live.md
@@ -0,0 +1,5 @@
+---
+'@freshmint/react': minor
+---
+
+Return transaction status from useTransaction
diff --git a/package-lock.json b/package-lock.json
index 9c7b6dc9..cbb801bf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,8 @@
],
"devDependencies": {
"@changesets/cli": "^2.25.2",
+ "@types/jest": "^28.1.6",
+ "@types/node": "^18.11.13",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"eslint": "^8.24.0",
"prettier": "latest",
@@ -2848,13 +2850,6 @@
"@sinonjs/commons": "^1.7.0"
}
},
- "node_modules/@tuplo/envsubst": {
- "version": "1.15.0",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/@types/babel__core": {
"version": "7.1.19",
"dev": true,
@@ -2996,8 +2991,9 @@
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
},
"node_modules/@types/node": {
- "version": "18.8.2",
- "license": "MIT"
+ "version": "18.11.15",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.15.tgz",
+ "integrity": "sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw=="
},
"node_modules/@types/node-fetch": {
"version": "2.6.2",
@@ -14076,7 +14072,6 @@
"dependencies": {
"@onflow/fcl": "^1.2.0",
"@onflow/flow-cadut": "^0.2.0-alpha.9",
- "@tuplo/envsubst": "^1.15.0",
"react": "^18.2.0",
"schema-utils": "^4.0.0"
},
@@ -14090,7 +14085,7 @@
},
"packages/core": {
"name": "@freshmint/core",
- "version": "0.4.0",
+ "version": "0.7.0",
"license": "Apache-2.0",
"dependencies": {
"@onflow/fcl": "^1.2.0",
@@ -14114,10 +14109,10 @@
}
},
"packages/freshmint": {
- "version": "0.2.0",
+ "version": "0.4.0",
"license": "Apache-2.0",
"dependencies": {
- "@freshmint/core": "^0.4.0",
+ "@freshmint/core": "^0.7.0",
"@ipld/car": "^4.1.6",
"@onflow/decode": "0.0.11",
"@onflow/flow-cadut": "^0.2.0-alpha.9",
@@ -15475,11 +15470,10 @@
"requires": {
"@onflow/fcl": "^1.2.0",
"@onflow/flow-cadut": "^0.2.0-alpha.9",
- "@tuplo/envsubst": "^1.15.0",
"@types/react": "^18.0.21",
"react": "^18.2.0",
"schema-utils": "^4.0.0",
- "tsup": "6.5.0"
+ "tsup": "^6.5.0"
}
},
"@freshmint/core": {
@@ -16422,9 +16416,6 @@
"@sinonjs/commons": "^1.7.0"
}
},
- "@tuplo/envsubst": {
- "version": "1.15.0"
- },
"@types/babel__core": {
"version": "7.1.19",
"dev": true,
@@ -16551,7 +16542,9 @@
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
},
"@types/node": {
- "version": "18.8.2"
+ "version": "18.11.15",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.15.tgz",
+ "integrity": "sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw=="
},
"@types/node-fetch": {
"version": "2.6.2",
@@ -18421,7 +18414,7 @@
"freshmint": {
"version": "file:packages/freshmint",
"requires": {
- "@freshmint/core": "^0.4.0",
+ "@freshmint/core": "^0.7.0",
"@ipld/car": "^4.1.6",
"@onflow/decode": "0.0.11",
"@onflow/flow-cadut": "^0.2.0-alpha.9",
diff --git a/packages/cadence-loader/index.ts b/packages/cadence-loader/index.ts
index fe2a22f6..2ba3821e 100644
--- a/packages/cadence-loader/index.ts
+++ b/packages/cadence-loader/index.ts
@@ -6,7 +6,6 @@ import { withPrefix } from '@onflow/fcl';
// @ts-ignore
import { extractImports } from '@onflow/flow-cadut';
-import envsubst from '@tuplo/envsubst';
import { validate } from 'schema-utils';
const schema: any = {
@@ -19,17 +18,25 @@ const schema: any = {
required: ['flowConfig'],
};
-function parseFlowConfigFile(configPath: string) {
- const rawConfig = fs.readFileSync(configPath).toString('utf8');
- const substitutedConfig = envsubst(rawConfig);
- return JSON.parse(substitutedConfig);
+function envsubst(s: string, env: { [key: string]: string }): string {
+ for (const key in env) {
+ s = s.replace(`$\{${key}}`, env[key]);
+ }
+
+ return s;
}
-function parseFlowConfigFiles(configPaths: string[]) {
- const configs = configPaths.map((configPath) => parseFlowConfigFile(configPath));
+function parseFlowConfigFiles(configPaths: string[], env: { [key: string]: string }) {
+ const configs = configPaths.map((configPath) => parseFlowConfigFile(configPath, env));
return mergeDeep({}, ...configs);
}
+function parseFlowConfigFile(configPath: string, env: { [key: string]: string }) {
+ const rawConfig = fs.readFileSync(configPath).toString('utf8');
+ const substitutedConfig = envsubst(rawConfig, env);
+ return JSON.parse(substitutedConfig);
+}
+
function isObject(item: any): boolean {
return item && typeof item === 'object' && !Array.isArray(item);
}
@@ -63,10 +70,10 @@ function mergeDeep(target: any, ...sources: any[]): any {
type AddressMap = { [contractName: string]: string };
type AddressMaps = { [network: string]: AddressMap };
-function getAddressMapsFromFlowConfig(configPath: string | string[]): AddressMaps {
+function getAddressMapsFromFlowConfig(configPath: string | string[], env: { [key: string]: string }): AddressMaps {
const configPaths = Array.isArray(configPath) ? configPath : [configPath];
- const config = parseFlowConfigFiles(configPaths);
+ const config = parseFlowConfigFiles(configPaths, env);
return {
emulator: getAddressMapForNetwork(config, 'emulator'),
@@ -208,7 +215,9 @@ export default function loader(this: WebpackLoader, source: string): string {
validate(schema, options);
- const addressMaps = getAddressMapsFromFlowConfig(options.flowConfig);
+ const env = options.env ?? {};
+
+ const addressMaps = getAddressMapsFromFlowConfig(options.flowConfig, env);
const extractedImports = extractImports(source);
diff --git a/packages/cadence-loader/package.json b/packages/cadence-loader/package.json
index b2043cba..37f04113 100644
--- a/packages/cadence-loader/package.json
+++ b/packages/cadence-loader/package.json
@@ -23,7 +23,6 @@
"dependencies": {
"@onflow/fcl": "^1.2.0",
"@onflow/flow-cadut": "^0.2.0-alpha.9",
- "@tuplo/envsubst": "^1.15.0",
"react": "^18.2.0",
"schema-utils": "^4.0.0"
},
diff --git a/packages/freshmint/config.ts b/packages/freshmint/config.ts
index face236a..5f1ffd14 100644
--- a/packages/freshmint/config.ts
+++ b/packages/freshmint/config.ts
@@ -82,9 +82,9 @@ export class MissingContractAccountForNetworkError extends FreshmintError {
constructor(network: string) {
super(
- `Please specify a contract account for the "${network}" network.\n\nExample in ${chalk.green(
- 'freshmint.yaml',
- )}:${chalk.cyan(`\n\ncontract:\n account:\n ${network}: your-account-name (as defined in flow.json)`)}`,
+ `Please specify a contract account for the "${network}" network.\n\nExample in freshmint.yaml:${chalk.cyan(
+ `\n\ncontract:\n account:\n ${network}: your-account-name (as defined in flow.json)`,
+ )}`,
);
this.network = network;
}
diff --git a/packages/freshmint/generate/templates/web/components/NFTDrop.tsx b/packages/freshmint/generate/templates/web/components/NFTDrop.tsx
index cd217f2c..062c6b52 100644
--- a/packages/freshmint/generate/templates/web/components/NFTDrop.tsx
+++ b/packages/freshmint/generate/templates/web/components/NFTDrop.tsx
@@ -1,6 +1,6 @@
import { useRouter } from 'next/router';
import { Box, Text, Button } from '@chakra-ui/react';
-import { useFCL, useScript, useTransaction, TransactionResult } from '@freshmint/react';
+import { useFCL, useScript, useTransaction, TransactionResult, TransactionStatus } from '@freshmint/react';
import getDrop from '../../cadence/scripts/get_drop.cdc';
import claimNFT from '../../cadence/transactions/claim_nft.cdc';
@@ -13,25 +13,6 @@ interface DropInfo {
paymentType: string;
}
-function parseDropResult(result: any | null): DropInfo | null {
- if (result === null) {
- return null;
- }
-
- return {
- id: result.id,
- supply: parseInt(result.supply, 10),
- size: parseInt(result.size, 10),
- price: parseFloat(result.price),
- paymentType: result.paymentVaultType.typeID,
- };
-}
-
-function parseClaimResult(result: TransactionResult): string {
- const event = result.events.find((e) => e.type.includes('FreshmintClaimSaleV2.NFTClaimed'))!;
- return event.data.nftID;
-}
-
interface DropProps {
address: string;
id?: string;
@@ -43,7 +24,7 @@ export default function NFTDrop({ address, id = 'default' }: DropProps) {
const [drop, isLoading] = useScript({ cadence: getDrop, args: [address, id] }, parseDropResult);
- const [nftId, claim] = useTransaction(claimNFT, parseClaimResult);
+ const [nftId, claim, status] = useTransaction(claimNFT, parseClaimResult);
if (nftId && currentUser) {
router.push(`/nfts/${currentUser.address}/${nftId}`);
@@ -58,9 +39,50 @@ export default function NFTDrop({ address, id = 'default' }: DropProps) {
{drop.supply > 0 ? `${drop.supply} / ${drop.size} NFTs available.` : `All ${drop.size} NFTs have been claimed.`}
-