create-awarizon-app 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/index.js +154 -0
  2. package/package.json +39 -0
  3. package/templates/expo/.env +1 -0
  4. package/templates/expo/.env.example +3 -0
  5. package/templates/expo/_gitignore +5 -0
  6. package/templates/expo/app/(tabs)/_layout.tsx +24 -0
  7. package/templates/expo/app/(tabs)/index.tsx +79 -0
  8. package/templates/expo/app/_layout.tsx +24 -0
  9. package/templates/expo/app.json +36 -0
  10. package/templates/expo/package.json +35 -0
  11. package/templates/expo/tsconfig.json +8 -0
  12. package/templates/expo-js/.env +1 -0
  13. package/templates/expo-js/.env.example +3 -0
  14. package/templates/expo-js/_gitignore +5 -0
  15. package/templates/expo-js/app/(tabs)/_layout.jsx +24 -0
  16. package/templates/expo-js/app/(tabs)/index.jsx +81 -0
  17. package/templates/expo-js/app/_layout.jsx +24 -0
  18. package/templates/expo-js/app.json +33 -0
  19. package/templates/expo-js/babel.config.js +6 -0
  20. package/templates/expo-js/jsconfig.json +12 -0
  21. package/templates/expo-js/package.json +33 -0
  22. package/templates/nextjs/.env.example +11 -0
  23. package/templates/nextjs/.env.local +4 -0
  24. package/templates/nextjs/_gitignore +6 -0
  25. package/templates/nextjs/app/globals.css +30 -0
  26. package/templates/nextjs/app/layout.tsx +29 -0
  27. package/templates/nextjs/app/page.tsx +168 -0
  28. package/templates/nextjs/components/ui/Badge.tsx +32 -0
  29. package/templates/nextjs/components/ui/Button.tsx +43 -0
  30. package/templates/nextjs/components/ui/Card.tsx +15 -0
  31. package/templates/nextjs/components/ui/Skeleton.tsx +7 -0
  32. package/templates/nextjs/components/ui/StatCard.tsx +24 -0
  33. package/templates/nextjs/lib/awarizon.ts +8 -0
  34. package/templates/nextjs/lib/utils.ts +3 -0
  35. package/templates/nextjs/next.config.ts +7 -0
  36. package/templates/nextjs/package.json +29 -0
  37. package/templates/nextjs/postcss.config.js +6 -0
  38. package/templates/nextjs/tailwind.config.ts +19 -0
  39. package/templates/nextjs/tsconfig.json +21 -0
  40. package/templates/nextjs-js/.env.example +11 -0
  41. package/templates/nextjs-js/.env.local +4 -0
  42. package/templates/nextjs-js/_gitignore +5 -0
  43. package/templates/nextjs-js/app/globals.css +30 -0
  44. package/templates/nextjs-js/app/layout.jsx +29 -0
  45. package/templates/nextjs-js/app/page.jsx +141 -0
  46. package/templates/nextjs-js/components/ui/Badge.jsx +24 -0
  47. package/templates/nextjs-js/components/ui/Button.jsx +25 -0
  48. package/templates/nextjs-js/components/ui/Card.jsx +9 -0
  49. package/templates/nextjs-js/components/ui/Skeleton.jsx +7 -0
  50. package/templates/nextjs-js/components/ui/StatCard.jsx +16 -0
  51. package/templates/nextjs-js/jsconfig.json +21 -0
  52. package/templates/nextjs-js/lib/awarizon.js +7 -0
  53. package/templates/nextjs-js/lib/utils.js +3 -0
  54. package/templates/nextjs-js/next.config.js +6 -0
  55. package/templates/nextjs-js/package.json +25 -0
  56. package/templates/nextjs-js/postcss.config.js +6 -0
  57. package/templates/nextjs-js/tailwind.config.js +16 -0
  58. package/templates/react/.env +1 -0
  59. package/templates/react/.env.example +7 -0
  60. package/templates/react/_gitignore +3 -0
  61. package/templates/react/index.html +12 -0
  62. package/templates/react/package.json +28 -0
  63. package/templates/react/postcss.config.js +6 -0
  64. package/templates/react/src/App.tsx +166 -0
  65. package/templates/react/src/components/ui/Badge.tsx +32 -0
  66. package/templates/react/src/components/ui/Button.tsx +43 -0
  67. package/templates/react/src/components/ui/Card.tsx +15 -0
  68. package/templates/react/src/components/ui/Skeleton.tsx +7 -0
  69. package/templates/react/src/components/ui/StatCard.tsx +24 -0
  70. package/templates/react/src/index.css +30 -0
  71. package/templates/react/src/lib/utils.ts +3 -0
  72. package/templates/react/src/main.tsx +22 -0
  73. package/templates/react/tailwind.config.js +15 -0
  74. package/templates/react/tsconfig.app.json +20 -0
  75. package/templates/react/tsconfig.json +7 -0
  76. package/templates/react/tsconfig.node.json +15 -0
  77. package/templates/react/vite.config.ts +6 -0
  78. package/templates/react-js/.env +1 -0
  79. package/templates/react-js/.env.example +7 -0
  80. package/templates/react-js/_gitignore +3 -0
  81. package/templates/react-js/index.html +12 -0
  82. package/templates/react-js/jsconfig.json +14 -0
  83. package/templates/react-js/package.json +25 -0
  84. package/templates/react-js/postcss.config.js +6 -0
  85. package/templates/react-js/src/App.jsx +139 -0
  86. package/templates/react-js/src/components/ui/Badge.jsx +24 -0
  87. package/templates/react-js/src/components/ui/Button.jsx +25 -0
  88. package/templates/react-js/src/components/ui/Card.jsx +9 -0
  89. package/templates/react-js/src/components/ui/Skeleton.jsx +7 -0
  90. package/templates/react-js/src/components/ui/StatCard.jsx +16 -0
  91. package/templates/react-js/src/index.css +30 -0
  92. package/templates/react-js/src/lib/utils.js +3 -0
  93. package/templates/react-js/src/main.jsx +22 -0
  94. package/templates/react-js/tailwind.config.js +15 -0
  95. package/templates/react-js/vite.config.js +6 -0
package/dist/index.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import * as p from "@clack/prompts";
5
+ import chalk from "chalk";
6
+ import { Command } from "commander";
7
+ import fs from "fs-extra";
8
+ import path from "path";
9
+ import { execSync } from "child_process";
10
+ import { fileURLToPath } from "url";
11
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ function detectPackageManager() {
13
+ const ua = process.env.npm_config_user_agent ?? "";
14
+ if (ua.startsWith("pnpm")) return "pnpm";
15
+ if (ua.startsWith("yarn")) return "yarn";
16
+ if (ua.startsWith("bun")) return "bun";
17
+ return "npm";
18
+ }
19
+ function installCmd(pm) {
20
+ return pm === "yarn" ? "yarn" : `${pm} install`;
21
+ }
22
+ function devCmd(pm, template) {
23
+ const script = template === "expo" ? "start" : "dev";
24
+ if (pm === "yarn") return `yarn ${script}`;
25
+ if (pm === "pnpm") return `pnpm ${script}`;
26
+ if (pm === "bun") return `bun run ${script}`;
27
+ return `npm run ${script}`;
28
+ }
29
+ function toPascalCase(str) {
30
+ return str.replace(/[-_\s]+(.)/g, (_, c) => c.toUpperCase()).replace(/^(.)/, (c) => c.toUpperCase());
31
+ }
32
+ async function processTemplate(dir, projectName, apiKey) {
33
+ const pascal = toPascalCase(projectName);
34
+ const entries = await fs.readdir(dir, { withFileTypes: true });
35
+ for (const entry of entries) {
36
+ const full = path.join(dir, entry.name);
37
+ if (entry.isDirectory()) {
38
+ await processTemplate(full, projectName, apiKey);
39
+ } else {
40
+ const text2 = await fs.readFile(full, "utf-8");
41
+ const replaced = text2.replaceAll("{{project-name}}", projectName).replaceAll("{{ProjectName}}", pascal).replaceAll("{{API_KEY}}", apiKey);
42
+ await fs.writeFile(full, replaced, "utf-8");
43
+ }
44
+ }
45
+ }
46
+ function resolveTemplateDir(template, lang) {
47
+ return lang === "js" ? `${template}-js` : template;
48
+ }
49
+ var program = new Command();
50
+ program.name("create-awarizon-app").description("Scaffold a new project with the Awarizon Web3 SDK").version("1.0.0").argument("[project-name]", "Directory name for the new project").option("-t, --template <template>", "Template: nextjs | react | expo").option("-l, --lang <lang>", "Language: ts | js (default: ts, expo always ts)").option("-k, --api-key <key>", "Your Awarizon API key (awz_live_...)").option("--skip-install", "Skip running npm install after scaffolding").option("--pm <pm>", "Package manager: npm | pnpm | yarn | bun").action(async (nameArg, opts) => {
51
+ console.log("");
52
+ p.intro(chalk.bold.white(" create-awarizon-app ") + chalk.dim(" \u2014 Awarizon Web3 SDK"));
53
+ let projectName = nameArg;
54
+ if (!projectName) {
55
+ const res = await p.text({
56
+ message: "Project name",
57
+ placeholder: "my-web3-app",
58
+ validate: (v) => v.trim() ? void 0 : "Project name is required"
59
+ });
60
+ if (p.isCancel(res)) {
61
+ p.cancel("Cancelled.");
62
+ process.exit(0);
63
+ }
64
+ projectName = res.trim();
65
+ }
66
+ let template = opts.template;
67
+ if (!template) {
68
+ const res = await p.select({
69
+ message: "Which template?",
70
+ options: [
71
+ { value: "nextjs", label: "Next.js 14", hint: "App Router \xB7 @awarizon/react hooks" },
72
+ { value: "react", label: "React + Vite", hint: "SPA \xB7 @awarizon/react hooks" },
73
+ { value: "expo", label: "Expo (React Native)", hint: "iOS + Android \xB7 TypeScript" }
74
+ ]
75
+ });
76
+ if (p.isCancel(res)) {
77
+ p.cancel("Cancelled.");
78
+ process.exit(0);
79
+ }
80
+ template = res;
81
+ }
82
+ let lang = opts.lang ?? "ts";
83
+ if (!opts.lang) {
84
+ const res = await p.select({
85
+ message: "Language",
86
+ options: [
87
+ { value: "ts", label: "TypeScript", hint: "Recommended \u2014 full type safety" },
88
+ { value: "js", label: "JavaScript", hint: "Plain JS with JSDoc hints" }
89
+ ]
90
+ });
91
+ if (p.isCancel(res)) {
92
+ p.cancel("Cancelled.");
93
+ process.exit(0);
94
+ }
95
+ lang = res;
96
+ }
97
+ let apiKey = opts.apiKey ?? "";
98
+ if (!apiKey) {
99
+ const res = await p.text({
100
+ message: "Awarizon API key",
101
+ placeholder: "awz_live_... (get one at awarizon.com/dashboard)",
102
+ validate: () => void 0
103
+ // optional — can skip
104
+ });
105
+ if (p.isCancel(res)) {
106
+ p.cancel("Cancelled.");
107
+ process.exit(0);
108
+ }
109
+ apiKey = (res ?? "").trim();
110
+ }
111
+ const pm = opts.pm ?? detectPackageManager();
112
+ const dest = path.resolve(process.cwd(), projectName);
113
+ if (await fs.pathExists(dest)) {
114
+ p.log.error(`Directory "${projectName}" already exists.`);
115
+ process.exit(1);
116
+ }
117
+ const templateKey = resolveTemplateDir(template, lang);
118
+ const templateDir = path.join(__dirname, "..", "templates", templateKey);
119
+ if (!await fs.pathExists(templateDir)) {
120
+ p.log.error(`Template "${templateKey}" not found. This is a bug \u2014 please report it.`);
121
+ process.exit(1);
122
+ }
123
+ const spinner2 = p.spinner();
124
+ spinner2.start("Copying template\u2026");
125
+ await fs.copy(templateDir, dest);
126
+ const gitignoreSrc = path.join(dest, "_gitignore");
127
+ if (await fs.pathExists(gitignoreSrc)) {
128
+ await fs.rename(gitignoreSrc, path.join(dest, ".gitignore"));
129
+ }
130
+ await processTemplate(dest, projectName, apiKey);
131
+ spinner2.stop("Template copied.");
132
+ if (!opts.skipInstall) {
133
+ spinner2.start(`Installing dependencies with ${pm}\u2026`);
134
+ try {
135
+ execSync(installCmd(pm), { cwd: dest, stdio: "pipe" });
136
+ spinner2.stop("Dependencies installed.");
137
+ } catch {
138
+ spinner2.stop(chalk.yellow("Install failed \u2014 run it manually."));
139
+ }
140
+ }
141
+ const langLabel = lang === "js" ? "JavaScript" : "TypeScript";
142
+ const templateLabels = {
143
+ nextjs: "Next.js 14",
144
+ react: "React + Vite",
145
+ expo: "Expo (React Native)"
146
+ };
147
+ p.outro(
148
+ chalk.green("\u2713 Project ready!") + "\n\n" + chalk.dim(` Template: `) + chalk.white(`${templateLabels[template]} \xB7 ${langLabel}`) + "\n" + chalk.bold("\n Next steps:\n") + chalk.dim(` cd ${projectName}
149
+ `) + (apiKey ? "" : chalk.dim(` # Add your API key to ${template === "expo" ? ".env" : ".env.local"}
150
+ `)) + chalk.dim(` ${devCmd(pm, template)}
151
+ `) + "\n" + chalk.dim(" Docs: ") + chalk.cyan("https://awarizon.com/docs") + "\n" + chalk.dim(" API keys: ") + chalk.cyan("https://awarizon.com/dashboard/api-keys")
152
+ );
153
+ });
154
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "create-awarizon-app",
3
+ "version": "1.0.0",
4
+ "description": "Scaffold a new project with the Awarizon Web3 SDK",
5
+ "keywords": ["awarizon", "web3", "evm", "create-app", "scaffold"],
6
+ "homepage": "https://awarizon.com/sdk",
7
+ "repository": "https://github.com/Awaizon-ltd/awarizon-sdk-core",
8
+ "license": "MIT",
9
+ "type": "module",
10
+ "bin": {
11
+ "create-awarizon-app": "./dist/index.js"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "templates"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch",
20
+ "clean": "rimraf dist"
21
+ },
22
+ "dependencies": {
23
+ "@clack/prompts": "^0.9.1",
24
+ "chalk": "^5.3.0",
25
+ "commander": "^12.1.0",
26
+ "fs-extra": "^11.2.0",
27
+ "ora": "^8.0.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/fs-extra": "^11.0.4",
31
+ "@types/node": "^20.0.0",
32
+ "rimraf": "^5.0.0",
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.5.0"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ }
39
+ }
@@ -0,0 +1 @@
1
+ EXPO_PUBLIC_AWARIZON_API_KEY={{API_KEY}}
@@ -0,0 +1,3 @@
1
+ # Get your API key at https://awarizon.com/dashboard/api-keys
2
+ # Expo Config: use expo-constants or expo-env to access this at runtime
3
+ EXPO_PUBLIC_AWARIZON_API_KEY={{API_KEY}}
@@ -0,0 +1,5 @@
1
+ .env
2
+ node_modules/
3
+ .expo/
4
+ dist/
5
+ web-build/
@@ -0,0 +1,24 @@
1
+ import { Tabs } from 'expo-router'
2
+ import { Platform } from 'react-native'
3
+
4
+ export default function TabLayout() {
5
+ return (
6
+ <Tabs
7
+ screenOptions={{
8
+ tabBarActiveTintColor: '#6366f1',
9
+ tabBarInactiveTintColor: '#6b7280',
10
+ tabBarStyle: {
11
+ backgroundColor: '#111',
12
+ borderTopColor: '#1f1f1f',
13
+ height: Platform.OS === 'ios' ? 88 : 60,
14
+ paddingBottom: Platform.OS === 'ios' ? 28 : 8,
15
+ },
16
+ headerStyle: { backgroundColor: '#000' },
17
+ headerTintColor: '#fff',
18
+ }}
19
+ >
20
+ <Tabs.Screen name="index" options={{ title: 'Home' }} />
21
+ <Tabs.Screen name="explorer" options={{ title: 'Explorer' }} />
22
+ </Tabs>
23
+ )
24
+ }
@@ -0,0 +1,79 @@
1
+ import { ScrollView, View, Text, StyleSheet, ActivityIndicator } from 'react-native'
2
+ import { useReadContract } from '@awarizon/react-native'
3
+
4
+ const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
5
+ const ERC20_ABI = [
6
+ { name: 'name', type: 'function', inputs: [], outputs: [{ type: 'string' }], stateMutability: 'view' },
7
+ { name: 'symbol', type: 'function', inputs: [], outputs: [{ type: 'string' }], stateMutability: 'view' },
8
+ { name: 'decimals', type: 'function', inputs: [], outputs: [{ type: 'uint8' }], stateMutability: 'view' },
9
+ { name: 'totalSupply', type: 'function', inputs: [], outputs: [{ type: 'uint256' }], stateMutability: 'view' },
10
+ ] as const
11
+
12
+ function usdc(fn: string) {
13
+ return useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: fn as never })
14
+ }
15
+
16
+ function Row({ label, value }: { label: string; value?: string }) {
17
+ return (
18
+ <View style={s.row}>
19
+ <Text style={s.label}>{label}</Text>
20
+ {value === undefined
21
+ ? <ActivityIndicator size="small" color="#6366f1" />
22
+ : <Text style={s.value}>{value}</Text>}
23
+ </View>
24
+ )
25
+ }
26
+
27
+ export default function HomeScreen() {
28
+ const { data: name } = usdc('name')
29
+ const { data: symbol } = usdc('symbol')
30
+ const { data: decimals } = usdc('decimals')
31
+ const { data: totalSupply } = usdc('totalSupply')
32
+
33
+ const formatted =
34
+ totalSupply !== undefined && decimals !== undefined
35
+ ? (Number(totalSupply) / 10 ** Number(decimals)).toLocaleString(undefined, { maximumFractionDigits: 2 })
36
+ : undefined
37
+
38
+ return (
39
+ <ScrollView style={s.bg} contentContainerStyle={s.container}>
40
+ <View style={s.hero}>
41
+ <Text style={s.badge}>{{ProjectName}}</Text>
42
+ <Text style={s.heading}>Live on-chain data</Text>
43
+ <Text style={s.sub}>Reading USDC on Base — no backend required.</Text>
44
+ </View>
45
+
46
+ <View style={s.card}>
47
+ <Text style={s.cardTitle}>USDC — Base</Text>
48
+ <Row label="Name" value={name as string | undefined} />
49
+ <Row label="Symbol" value={symbol as string | undefined} />
50
+ <Row label="Decimals" value={decimals !== undefined ? String(decimals) : undefined} />
51
+ <Row label="Total Supply" value={formatted} />
52
+ </View>
53
+
54
+ <View style={s.card}>
55
+ <Text style={s.cardTitle}>Next steps</Text>
56
+ <Text style={s.step}>1. Replace USDC_BASE with your contract address</Text>
57
+ <Text style={s.step}>2. Swap ERC20_ABI for your contract ABI</Text>
58
+ <Text style={s.step}>3. Change the chain in app/_layout.tsx</Text>
59
+ <Text style={s.step}>4. Use <Text style={s.code}>useWriteContract</Text> for transactions</Text>
60
+ </View>
61
+ </ScrollView>
62
+ )
63
+ }
64
+
65
+ const s = StyleSheet.create({
66
+ bg: { flex: 1, backgroundColor: '#0a0a0a' },
67
+ container: { padding: 20, paddingBottom: 40 },
68
+ hero: { marginBottom: 24 },
69
+ badge: { color: '#6366f1', fontSize: 12, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 1.5, marginBottom: 8 },
70
+ heading: { color: '#fff', fontSize: 28, fontWeight: '800', marginBottom: 6 },
71
+ sub: { color: '#9ca3af', fontSize: 15, lineHeight: 22 },
72
+ card: { backgroundColor: '#111', borderWidth: 1, borderColor: '#1f1f1f', borderRadius: 12, padding: 16, marginBottom: 16 },
73
+ cardTitle: { color: '#fff', fontWeight: '700', fontSize: 15, marginBottom: 12 },
74
+ row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#1f1f1f' },
75
+ label: { color: '#9ca3af', fontSize: 13 },
76
+ value: { color: '#e5e7eb', fontSize: 13, fontWeight: '500', fontFamily: 'monospace' },
77
+ step: { color: '#9ca3af', fontSize: 13, lineHeight: 22, marginBottom: 4 },
78
+ code: { color: '#6366f1', fontFamily: 'monospace' },
79
+ })
@@ -0,0 +1,24 @@
1
+ import { Stack } from 'expo-router'
2
+ import { AwarizonProvider } from '@awarizon/react-native'
3
+
4
+ export default function RootLayout() {
5
+ return (
6
+ /*
7
+ AwarizonProvider makes the SDK available throughout the app.
8
+ chain: EVM network — base, ethereum, polygon, etc.
9
+ apiKey: from EXPO_PUBLIC_AWARIZON_API_KEY in .env
10
+ */
11
+ <AwarizonProvider
12
+ chain="base"
13
+ apiKey={process.env.EXPO_PUBLIC_AWARIZON_API_KEY!}
14
+ >
15
+ <Stack
16
+ screenOptions={{
17
+ headerStyle: { backgroundColor: '#000' },
18
+ headerTintColor: '#fff',
19
+ contentStyle: { backgroundColor: '#0a0a0a' },
20
+ }}
21
+ />
22
+ </AwarizonProvider>
23
+ )
24
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{ProjectName}}",
4
+ "slug": "{{project-name}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/images/icon.png",
8
+ "scheme": "{{project-name}}",
9
+ "userInterfaceStyle": "automatic",
10
+ "splash": {
11
+ "image": "./assets/images/splash.png",
12
+ "resizeMode": "contain",
13
+ "backgroundColor": "#000000"
14
+ },
15
+ "ios": {
16
+ "supportsTablet": true,
17
+ "bundleIdentifier": "com.awarizon.{{project-name}}"
18
+ },
19
+ "android": {
20
+ "adaptiveIcon": {
21
+ "foregroundImage": "./assets/images/adaptive-icon.png",
22
+ "backgroundColor": "#000000"
23
+ },
24
+ "package": "com.awarizon.{{project-name}}"
25
+ },
26
+ "web": {
27
+ "bundler": "metro",
28
+ "output": "static",
29
+ "favicon": "./assets/images/favicon.png"
30
+ },
31
+ "plugins": ["expo-router", "expo-secure-store"],
32
+ "experiments": {
33
+ "typedRoutes": true
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "{{project-name}}",
3
+ "version": "1.0.0",
4
+ "main": "expo-router/entry",
5
+ "scripts": {
6
+ "start": "expo start",
7
+ "android": "expo start --android",
8
+ "ios": "expo start --ios",
9
+ "web": "expo start --web"
10
+ },
11
+ "dependencies": {
12
+ "@awarizon/react-native": "latest",
13
+ "@awarizon/web3": "latest",
14
+ "@expo/vector-icons": "^14.0.2",
15
+ "expo": "~51.0.0",
16
+ "expo-constants": "~16.0.2",
17
+ "expo-font": "~12.0.9",
18
+ "expo-linking": "~6.3.1",
19
+ "expo-router": "~3.5.17",
20
+ "expo-secure-store": "~13.0.2",
21
+ "expo-splash-screen": "~0.27.5",
22
+ "expo-status-bar": "~1.12.1",
23
+ "expo-system-ui": "~3.0.7",
24
+ "react": "18.2.0",
25
+ "react-dom": "18.2.0",
26
+ "react-native": "0.74.5",
27
+ "react-native-safe-area-context": "4.10.5",
28
+ "react-native-screens": "3.31.1"
29
+ },
30
+ "devDependencies": {
31
+ "@babel/core": "^7.24.0",
32
+ "@types/react": "~18.2.45",
33
+ "typescript": "^5.3.3"
34
+ }
35
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "expo/tsconfig.base",
3
+ "compilerOptions": {
4
+ "strict": true,
5
+ "paths": { "@/*": ["./*"] }
6
+ },
7
+ "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
8
+ }
@@ -0,0 +1 @@
1
+ EXPO_PUBLIC_AWARIZON_API_KEY={{API_KEY}}
@@ -0,0 +1,3 @@
1
+ # Get your API key at https://awarizon.com/dashboard/api-keys
2
+ # Expo Config: use expo-constants or expo-env to access this at runtime
3
+ EXPO_PUBLIC_AWARIZON_API_KEY={{API_KEY}}
@@ -0,0 +1,5 @@
1
+ .env
2
+ node_modules/
3
+ .expo/
4
+ dist/
5
+ web-build/
@@ -0,0 +1,24 @@
1
+ import { Tabs } from 'expo-router'
2
+ import { Platform } from 'react-native'
3
+
4
+ export default function TabLayout() {
5
+ return (
6
+ <Tabs
7
+ screenOptions={{
8
+ tabBarActiveTintColor: '#6366f1',
9
+ tabBarInactiveTintColor: '#6b7280',
10
+ tabBarStyle: {
11
+ backgroundColor: '#111',
12
+ borderTopColor: '#1f1f1f',
13
+ height: Platform.OS === 'ios' ? 88 : 60,
14
+ paddingBottom: Platform.OS === 'ios' ? 28 : 8,
15
+ },
16
+ headerStyle: { backgroundColor: '#000' },
17
+ headerTintColor: '#fff',
18
+ }}
19
+ >
20
+ <Tabs.Screen name="index" options={{ title: 'Home' }} />
21
+ <Tabs.Screen name="explorer" options={{ title: 'Explorer' }} />
22
+ </Tabs>
23
+ )
24
+ }
@@ -0,0 +1,81 @@
1
+ import { ScrollView, View, Text, StyleSheet, ActivityIndicator } from 'react-native'
2
+ import { useReadContract } from '@awarizon/react-native'
3
+
4
+ const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
5
+
6
+ /** @type {readonly object[]} */
7
+ const ERC20_ABI = [
8
+ { name: 'name', type: 'function', inputs: [], outputs: [{ type: 'string' }], stateMutability: 'view' },
9
+ { name: 'symbol', type: 'function', inputs: [], outputs: [{ type: 'string' }], stateMutability: 'view' },
10
+ { name: 'decimals', type: 'function', inputs: [], outputs: [{ type: 'uint8' }], stateMutability: 'view' },
11
+ { name: 'totalSupply', type: 'function', inputs: [], outputs: [{ type: 'uint256' }], stateMutability: 'view' },
12
+ ]
13
+
14
+ function usdc(fn) {
15
+ return useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: fn })
16
+ }
17
+
18
+ function Row({ label, value }) {
19
+ return (
20
+ <View style={s.row}>
21
+ <Text style={s.label}>{label}</Text>
22
+ {value === undefined
23
+ ? <ActivityIndicator size="small" color="#6366f1" />
24
+ : <Text style={s.value}>{value}</Text>}
25
+ </View>
26
+ )
27
+ }
28
+
29
+ export default function HomeScreen() {
30
+ const { data: name } = usdc('name')
31
+ const { data: symbol } = usdc('symbol')
32
+ const { data: decimals } = usdc('decimals')
33
+ const { data: totalSupply } = usdc('totalSupply')
34
+
35
+ const formatted =
36
+ totalSupply !== undefined && decimals !== undefined
37
+ ? (Number(totalSupply) / 10 ** Number(decimals)).toLocaleString(undefined, { maximumFractionDigits: 2 })
38
+ : undefined
39
+
40
+ return (
41
+ <ScrollView style={s.bg} contentContainerStyle={s.container}>
42
+ <View style={s.hero}>
43
+ <Text style={s.badge}>{{ProjectName}}</Text>
44
+ <Text style={s.heading}>Live on-chain data</Text>
45
+ <Text style={s.sub}>Reading USDC on Base — no backend required.</Text>
46
+ </View>
47
+
48
+ <View style={s.card}>
49
+ <Text style={s.cardTitle}>USDC — Base</Text>
50
+ <Row label="Name" value={name !== undefined ? String(name) : undefined} />
51
+ <Row label="Symbol" value={symbol !== undefined ? String(symbol) : undefined} />
52
+ <Row label="Decimals" value={decimals !== undefined ? String(decimals) : undefined} />
53
+ <Row label="Total Supply" value={formatted} />
54
+ </View>
55
+
56
+ <View style={s.card}>
57
+ <Text style={s.cardTitle}>Next steps</Text>
58
+ <Text style={s.step}>1. Replace USDC_BASE with your contract address</Text>
59
+ <Text style={s.step}>2. Swap ERC20_ABI for your contract ABI</Text>
60
+ <Text style={s.step}>3. Change the chain in app/_layout.jsx</Text>
61
+ <Text style={s.step}>4. Use <Text style={s.code}>useWriteContract</Text> for transactions</Text>
62
+ </View>
63
+ </ScrollView>
64
+ )
65
+ }
66
+
67
+ const s = StyleSheet.create({
68
+ bg: { flex: 1, backgroundColor: '#0a0a0a' },
69
+ container: { padding: 20, paddingBottom: 40 },
70
+ hero: { marginBottom: 24 },
71
+ badge: { color: '#6366f1', fontSize: 12, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 1.5, marginBottom: 8 },
72
+ heading: { color: '#fff', fontSize: 28, fontWeight: '800', marginBottom: 6 },
73
+ sub: { color: '#9ca3af', fontSize: 15, lineHeight: 22 },
74
+ card: { backgroundColor: '#111', borderWidth: 1, borderColor: '#1f1f1f', borderRadius: 12, padding: 16, marginBottom: 16 },
75
+ cardTitle: { color: '#fff', fontWeight: '700', fontSize: 15, marginBottom: 12 },
76
+ row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#1f1f1f' },
77
+ label: { color: '#9ca3af', fontSize: 13 },
78
+ value: { color: '#e5e7eb', fontSize: 13, fontWeight: '500', fontFamily: 'monospace' },
79
+ step: { color: '#9ca3af', fontSize: 13, lineHeight: 22, marginBottom: 4 },
80
+ code: { color: '#6366f1', fontFamily: 'monospace' },
81
+ })
@@ -0,0 +1,24 @@
1
+ import { Stack } from 'expo-router'
2
+ import { AwarizonProvider } from '@awarizon/react-native'
3
+
4
+ export default function RootLayout() {
5
+ return (
6
+ /*
7
+ AwarizonProvider makes the SDK available throughout the app.
8
+ chain: EVM network — base, ethereum, polygon, etc.
9
+ apiKey: from EXPO_PUBLIC_AWARIZON_API_KEY in .env
10
+ */
11
+ <AwarizonProvider
12
+ chain="base"
13
+ apiKey={process.env.EXPO_PUBLIC_AWARIZON_API_KEY}
14
+ >
15
+ <Stack
16
+ screenOptions={{
17
+ headerStyle: { backgroundColor: '#000' },
18
+ headerTintColor: '#fff',
19
+ contentStyle: { backgroundColor: '#0a0a0a' },
20
+ }}
21
+ />
22
+ </AwarizonProvider>
23
+ )
24
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{ProjectName}}",
4
+ "slug": "{{project-name}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/images/icon.png",
8
+ "scheme": "{{project-name}}",
9
+ "userInterfaceStyle": "automatic",
10
+ "splash": {
11
+ "image": "./assets/images/splash.png",
12
+ "resizeMode": "contain",
13
+ "backgroundColor": "#000000"
14
+ },
15
+ "ios": {
16
+ "supportsTablet": true,
17
+ "bundleIdentifier": "com.awarizon.{{project-name}}"
18
+ },
19
+ "android": {
20
+ "adaptiveIcon": {
21
+ "foregroundImage": "./assets/images/adaptive-icon.png",
22
+ "backgroundColor": "#000000"
23
+ },
24
+ "package": "com.awarizon.{{project-name}}"
25
+ },
26
+ "web": {
27
+ "bundler": "metro",
28
+ "output": "static",
29
+ "favicon": "./assets/images/favicon.png"
30
+ },
31
+ "plugins": ["expo-router", "expo-secure-store"]
32
+ }
33
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = function (api) {
2
+ api.cache(true)
3
+ return {
4
+ presets: ['babel-preset-expo'],
5
+ }
6
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["ES2020"],
5
+ "allowJs": true,
6
+ "checkJs": false,
7
+ "jsx": "react-native",
8
+ "paths": { "@/*": ["./*"] }
9
+ },
10
+ "include": ["**/*.js", "**/*.jsx"],
11
+ "exclude": ["node_modules", ".expo"]
12
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "{{project-name}}",
3
+ "version": "1.0.0",
4
+ "main": "expo-router/entry",
5
+ "scripts": {
6
+ "start": "expo start",
7
+ "android": "expo start --android",
8
+ "ios": "expo start --ios",
9
+ "web": "expo start --web"
10
+ },
11
+ "dependencies": {
12
+ "@awarizon/react-native": "latest",
13
+ "@awarizon/web3": "latest",
14
+ "@expo/vector-icons": "^14.0.2",
15
+ "expo": "~51.0.0",
16
+ "expo-constants": "~16.0.2",
17
+ "expo-font": "~12.0.9",
18
+ "expo-linking": "~6.3.1",
19
+ "expo-router": "~3.5.17",
20
+ "expo-secure-store": "~13.0.2",
21
+ "expo-splash-screen": "~0.27.5",
22
+ "expo-status-bar": "~1.12.1",
23
+ "expo-system-ui": "~3.0.7",
24
+ "react": "18.2.0",
25
+ "react-dom": "18.2.0",
26
+ "react-native": "0.74.5",
27
+ "react-native-safe-area-context": "4.10.5",
28
+ "react-native-screens": "3.31.1"
29
+ },
30
+ "devDependencies": {
31
+ "@babel/core": "^7.24.0"
32
+ }
33
+ }