create-avalanche-app 0.1.0 → 0.1.1

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 (30) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/icm-messenger/CLAUDE.md +68 -0
  5. package/templates/icm-messenger/README.md +59 -0
  6. package/templates/icm-messenger/app/globals.css +95 -0
  7. package/templates/icm-messenger/app/layout.tsx +23 -0
  8. package/templates/icm-messenger/app/page.tsx +5 -0
  9. package/templates/icm-messenger/app/providers.tsx +22 -0
  10. package/templates/icm-messenger/components/demo.tsx +412 -0
  11. package/templates/icm-messenger/contracts/cache/solidity-files-cache.json +1 -0
  12. package/templates/icm-messenger/contracts/foundry.toml +6 -0
  13. package/templates/icm-messenger/contracts/out/AvaKitMessenger.sol/AvaKitMessenger.json +1 -0
  14. package/templates/icm-messenger/contracts/out/AvaKitMessenger.sol/ITeleporterMessenger.json +1 -0
  15. package/templates/icm-messenger/contracts/out/AvaKitMessenger.sol/ITeleporterReceiver.json +1 -0
  16. package/templates/icm-messenger/contracts/out/build-info/790b55b96be74f23.json +1 -0
  17. package/templates/icm-messenger/contracts/src/AvaKitMessenger.sol +97 -0
  18. package/templates/icm-messenger/cursor/rules/avakit.mdc +32 -0
  19. package/templates/icm-messenger/env.example +6 -0
  20. package/templates/icm-messenger/gitignore +15 -0
  21. package/templates/icm-messenger/icm.config.json +6 -0
  22. package/templates/icm-messenger/lib/devnet.ts +58 -0
  23. package/templates/icm-messenger/lib/messenger-artifact.ts +184 -0
  24. package/templates/icm-messenger/llms.txt +39 -0
  25. package/templates/icm-messenger/manifest.json +6 -0
  26. package/templates/icm-messenger/next.config.ts +7 -0
  27. package/templates/icm-messenger/package.json +33 -0
  28. package/templates/icm-messenger/postcss.config.mjs +7 -0
  29. package/templates/icm-messenger/scripts/devnet.sh +106 -0
  30. package/templates/icm-messenger/tsconfig.json +23 -0
@@ -0,0 +1,412 @@
1
+ "use client";
2
+
3
+ import {
4
+ deployContract,
5
+ ensureChain,
6
+ getPublicClient,
7
+ getWalletClient,
8
+ readContract,
9
+ } from "@avakit/core";
10
+ import type { AvaChain } from "@avakit/core/chains";
11
+ import {
12
+ Button,
13
+ ConnectAvalanche,
14
+ shortenAddress,
15
+ useAvaAccount,
16
+ useAvaChain,
17
+ useAvaKit,
18
+ } from "@avakit/react";
19
+ import { ArrowRight, Check, Copy, Moon, Sun } from "lucide-react";
20
+ import { useTheme } from "next-themes";
21
+ import { useCallback, useEffect, useState } from "react";
22
+ import type { Address } from "viem";
23
+ import { blockchainIdOf, chain1, chain2, icm, isConfigured } from "@/lib/devnet";
24
+ import { abi, bytecode } from "@/lib/messenger-artifact";
25
+
26
+ const STORAGE_KEY = "icm-messenger:addresses";
27
+ const CHAINS: [AvaChain, AvaChain] = [chain1, chain2];
28
+
29
+ type AddrMap = Record<number, Address>;
30
+ type ChainStatus = { online: boolean; block: bigint; icmReady: boolean };
31
+ type Inbox = { message: string; count: bigint };
32
+
33
+ function loadAddrs(): AddrMap {
34
+ if (typeof window === "undefined") return {};
35
+ try {
36
+ return JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "{}") as AddrMap;
37
+ } catch {
38
+ return {};
39
+ }
40
+ }
41
+
42
+ export function Demo() {
43
+ const { address, isConnected } = useAvaAccount();
44
+ const { provider } = useAvaKit();
45
+ const { setChain } = useAvaChain();
46
+
47
+ const [addrs, setAddrs] = useState<AddrMap>({});
48
+ const [status, setStatus] = useState<Record<number, ChainStatus>>({});
49
+ const [inbox, setInbox] = useState<Record<number, Inbox>>({});
50
+ const [busy, setBusy] = useState<string | null>(null);
51
+ const [text, setText] = useState("gm from the other chain");
52
+ const [source, setSource] = useState<AvaChain>(chain1);
53
+ const [inFlight, setInFlight] = useState<string | null>(null);
54
+ const [error, setError] = useState<string | null>(null);
55
+
56
+ const destination = source.id === chain1.id ? chain2 : chain1;
57
+ const bothDeployed = Boolean(addrs[chain1.id] && addrs[chain2.id]);
58
+
59
+ useEffect(() => {
60
+ setAddrs(loadAddrs());
61
+ }, []);
62
+
63
+ const setAddr = useCallback((chainId: number, addr: Address) => {
64
+ setAddrs((prev) => {
65
+ const next = { ...prev, [chainId]: addr };
66
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
67
+ return next;
68
+ });
69
+ }, []);
70
+
71
+ // Live poll: chain liveness (block height), ICM readiness (Teleporter has
72
+ // code), and each deployed messenger's inbox. Read-only — no wallet needed.
73
+ useEffect(() => {
74
+ if (!isConfigured) return;
75
+ let active = true;
76
+ async function poll() {
77
+ const nextStatus: Record<number, ChainStatus> = {};
78
+ const nextInbox: Record<number, Inbox> = {};
79
+ await Promise.all(
80
+ CHAINS.map(async (chain) => {
81
+ const client = getPublicClient(chain);
82
+ try {
83
+ const [block, code] = await Promise.all([
84
+ client.getBlockNumber(),
85
+ client.getCode({ address: icm.teleporterMessenger as Address }),
86
+ ]);
87
+ nextStatus[chain.id] = { online: true, block, icmReady: Boolean(code && code !== "0x") };
88
+ } catch {
89
+ nextStatus[chain.id] = { online: false, block: 0n, icmReady: false };
90
+ }
91
+ const messenger = loadAddrs()[chain.id];
92
+ if (messenger) {
93
+ try {
94
+ const [message, count] = await Promise.all([
95
+ readContract(chain, { address: messenger, abi, functionName: "lastMessage" }),
96
+ readContract(chain, { address: messenger, abi, functionName: "messagesReceived" }),
97
+ ]);
98
+ nextInbox[chain.id] = { message: message as string, count: count as bigint };
99
+ } catch {
100
+ // messenger not ready
101
+ }
102
+ }
103
+ }),
104
+ );
105
+ if (active) {
106
+ setStatus(nextStatus);
107
+ setInbox(nextInbox);
108
+ }
109
+ }
110
+ void poll();
111
+ const timer = setInterval(poll, 3000);
112
+ return () => {
113
+ active = false;
114
+ clearInterval(timer);
115
+ };
116
+ }, [isConfigured]);
117
+
118
+ // Clear the in-flight banner once the destination inbox shows the message.
119
+ useEffect(() => {
120
+ if (inFlight && inbox[destination.id]?.message === inFlight) setInFlight(null);
121
+ }, [inFlight, inbox, destination.id]);
122
+
123
+ const deployOn = useCallback(
124
+ async (chain: AvaChain) => {
125
+ if (!provider || !address) return;
126
+ setBusy(`deploy:${chain.id}`);
127
+ setError(null);
128
+ try {
129
+ await ensureChain(provider, chain);
130
+ setChain(chain);
131
+ const { address: deployed } = await deployContract({
132
+ artifact: { abi, bytecode },
133
+ chain,
134
+ provider,
135
+ account: address,
136
+ });
137
+ setAddr(chain.id, deployed);
138
+ } catch (e) {
139
+ setError(e instanceof Error ? e.message : String(e));
140
+ } finally {
141
+ setBusy(null);
142
+ }
143
+ },
144
+ [provider, address, setAddr, setChain],
145
+ );
146
+
147
+ const sendMessage = useCallback(async () => {
148
+ if (!provider || !address) return;
149
+ const from = addrs[source.id];
150
+ const to = addrs[destination.id];
151
+ if (!from || !to) return;
152
+ setBusy("send");
153
+ setError(null);
154
+ try {
155
+ await ensureChain(provider, source);
156
+ setChain(source);
157
+ const wallet = getWalletClient(source, provider);
158
+ await wallet.writeContract({
159
+ address: from,
160
+ abi,
161
+ functionName: "sendMessage",
162
+ args: [blockchainIdOf(destination), to, text],
163
+ account: address,
164
+ } as never);
165
+ setInFlight(text);
166
+ } catch (e) {
167
+ setError(e instanceof Error ? e.message : String(e));
168
+ } finally {
169
+ setBusy(null);
170
+ }
171
+ }, [provider, address, addrs, source, destination, text, setChain]);
172
+
173
+ if (!isConfigured) {
174
+ return (
175
+ <Shell>
176
+ <SetupPanel />
177
+ </Shell>
178
+ );
179
+ }
180
+
181
+ return (
182
+ <Shell>
183
+ <div className="flex flex-col gap-2">
184
+ <h1 className="text-3xl font-semibold tracking-tight">Devnet Studio</h1>
185
+ <p className="text-muted-foreground text-sm">
186
+ Two Avalanche L1s, live. Deploy the messenger on each, then send a message across —
187
+ Interchain Messaging carries it and you watch it land on the other chain.
188
+ </p>
189
+ </div>
190
+
191
+ <section className="grid grid-cols-1 gap-3 sm:grid-cols-2">
192
+ {CHAINS.map((chain) => (
193
+ <ChainCard
194
+ key={chain.id}
195
+ chain={chain}
196
+ status={status[chain.id]}
197
+ messenger={addrs[chain.id]}
198
+ inbox={inbox[chain.id]}
199
+ isDestination={inFlight != null && chain.id === destination.id}
200
+ busy={busy === `deploy:${chain.id}`}
201
+ canDeploy={isConnected && !!address}
202
+ onDeploy={() => deployOn(chain)}
203
+ />
204
+ ))}
205
+ </section>
206
+
207
+ <section className="flex flex-col gap-3 rounded-xl border p-6">
208
+ <div className="flex items-center justify-between">
209
+ <div className="text-muted-foreground flex items-center gap-2 text-sm">
210
+ <span className="font-mono">{source.name}</span>
211
+ <ArrowRight className="size-4" />
212
+ <span className="font-mono">{destination.name}</span>
213
+ </div>
214
+ {!isConnected || !address ? <ConnectAvalanche /> : null}
215
+ </div>
216
+ <input
217
+ value={text}
218
+ onChange={(e) => setText(e.target.value)}
219
+ placeholder="Message to send cross-chain"
220
+ className="border-input bg-background rounded-lg border px-3 py-2 text-sm outline-none"
221
+ />
222
+ <div className="flex gap-2">
223
+ <Button
224
+ variant="outline"
225
+ size="sm"
226
+ onClick={() => setSource(destination)}
227
+ disabled={busy === "send"}
228
+ >
229
+ Swap direction
230
+ </Button>
231
+ <Button
232
+ onClick={sendMessage}
233
+ disabled={!bothDeployed || !isConnected || busy === "send" || !text}
234
+ className="flex-1"
235
+ >
236
+ {busy === "send" ? "Sending…" : `Send to ${destination.name}`}
237
+ </Button>
238
+ </div>
239
+ {!bothDeployed ? (
240
+ <p className="text-muted-foreground text-xs">
241
+ Deploy the messenger on both chains to enable sending.
242
+ </p>
243
+ ) : null}
244
+ {inFlight ? (
245
+ <p className="flex items-center gap-2 text-sm">
246
+ <span className="bg-foreground size-2 animate-ping rounded-full" />
247
+ In flight to {destination.name} — the relayer is delivering “{inFlight}”…
248
+ </p>
249
+ ) : null}
250
+ </section>
251
+
252
+ {error ? <p className="text-muted-foreground text-sm break-all">{error}</p> : null}
253
+ </Shell>
254
+ );
255
+ }
256
+
257
+ function ChainCard({
258
+ chain,
259
+ status,
260
+ messenger,
261
+ inbox,
262
+ isDestination,
263
+ busy,
264
+ canDeploy,
265
+ onDeploy,
266
+ }: {
267
+ chain: AvaChain;
268
+ status?: ChainStatus;
269
+ messenger?: Address;
270
+ inbox?: Inbox;
271
+ isDestination: boolean;
272
+ busy: boolean;
273
+ canDeploy: boolean;
274
+ onDeploy: () => void;
275
+ }) {
276
+ const online = status?.online ?? false;
277
+ return (
278
+ <div
279
+ className={`flex flex-col gap-3 rounded-xl border p-5 transition-colors ${
280
+ isDestination ? "border-foreground" : ""
281
+ }`}
282
+ >
283
+ <div className="flex items-center justify-between">
284
+ <span className="font-mono text-sm font-semibold">{chain.name}</span>
285
+ <span className="text-muted-foreground flex items-center gap-1.5 text-xs">
286
+ <span
287
+ className={`size-2 rounded-full ${online ? "bg-foreground animate-pulse" : "bg-muted-foreground/40"}`}
288
+ />
289
+ {online ? `block ${status?.block ?? 0n}` : "offline"}
290
+ </span>
291
+ </div>
292
+
293
+ <div className="flex flex-col gap-1.5">
294
+ <Row label="Chain ID" value={String(chain.id)} mono />
295
+ <Row
296
+ label="ICM"
297
+ value={status?.icmReady ? "✓ Teleporter ready" : "—"}
298
+ mono
299
+ />
300
+ {messenger ? (
301
+ <Row label="Messenger" value={shortenAddress(messenger, 6)} mono />
302
+ ) : null}
303
+ </div>
304
+
305
+ {messenger ? (
306
+ <div className="bg-muted/50 rounded-lg p-3">
307
+ <p className="text-muted-foreground text-xs">Last received</p>
308
+ <p className="truncate text-sm">{inbox?.message || "—"}</p>
309
+ <p className="text-muted-foreground mt-1 text-xs">
310
+ {inbox?.count ? `${inbox.count} total` : "0 total"}
311
+ </p>
312
+ </div>
313
+ ) : (
314
+ <Button onClick={onDeploy} disabled={busy || !canDeploy} size="sm">
315
+ {busy ? "Deploying…" : "Deploy messenger"}
316
+ </Button>
317
+ )}
318
+ </div>
319
+ );
320
+ }
321
+
322
+ function SetupPanel() {
323
+ return (
324
+ <div className="flex flex-col gap-4 rounded-xl border p-8">
325
+ <div className="flex flex-col gap-2">
326
+ <h1 className="text-2xl font-semibold tracking-tight">Spin up your cross-chain devnet</h1>
327
+ <p className="text-muted-foreground text-sm">
328
+ This app sends a message between two Avalanche L1s. Bring them up — with Interchain
329
+ Messaging and a relayer wired automatically — with one command in your terminal:
330
+ </p>
331
+ </div>
332
+ <CopyCommand command="pnpm devnet" />
333
+ <p className="text-muted-foreground text-xs">
334
+ Needs{" "}
335
+ <a
336
+ href="https://build.avax.network/docs/tooling/avalanche-cli/get-avalanche-cli"
337
+ target="_blank"
338
+ rel="noreferrer"
339
+ className="underline underline-offset-4"
340
+ >
341
+ avalanche-cli
342
+ </a>
343
+ . When it finishes it writes <span className="font-mono">icm.config.json</span> and this page
344
+ turns into the Devnet Studio automatically.
345
+ </p>
346
+ </div>
347
+ );
348
+ }
349
+
350
+ function CopyCommand({ command }: { command: string }) {
351
+ const [copied, setCopied] = useState(false);
352
+ return (
353
+ <button
354
+ type="button"
355
+ onClick={() => {
356
+ void navigator.clipboard?.writeText(command);
357
+ setCopied(true);
358
+ setTimeout(() => setCopied(false), 1500);
359
+ }}
360
+ className="bg-muted hover:bg-muted/70 flex items-center justify-between gap-4 rounded-lg p-4 text-left font-mono text-sm transition-colors"
361
+ >
362
+ <span>
363
+ <span className="text-muted-foreground select-none">$ </span>
364
+ {command}
365
+ </span>
366
+ {copied ? (
367
+ <Check className="size-4 shrink-0" />
368
+ ) : (
369
+ <Copy className="text-muted-foreground size-4 shrink-0" />
370
+ )}
371
+ </button>
372
+ );
373
+ }
374
+
375
+ function ThemeToggle() {
376
+ const { resolvedTheme, setTheme } = useTheme();
377
+ return (
378
+ <Button
379
+ variant="outline"
380
+ size="icon"
381
+ aria-label="Toggle theme"
382
+ onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
383
+ >
384
+ <Sun className="hidden size-4 dark:block" />
385
+ <Moon className="block size-4 dark:hidden" />
386
+ </Button>
387
+ );
388
+ }
389
+
390
+ function Shell({ children }: { children: React.ReactNode }) {
391
+ return (
392
+ <div className="mx-auto flex min-h-dvh max-w-2xl flex-col gap-8 px-6 py-16">
393
+ <header className="flex items-center justify-between">
394
+ <span className="font-mono text-sm font-semibold">__PROJECT_NAME__</span>
395
+ <div className="flex items-center gap-2">
396
+ <ConnectAvalanche />
397
+ <ThemeToggle />
398
+ </div>
399
+ </header>
400
+ {children}
401
+ </div>
402
+ );
403
+ }
404
+
405
+ function Row({ label, value, mono }: { label: string; value: string; mono?: boolean }) {
406
+ return (
407
+ <div className="flex items-center justify-between gap-4">
408
+ <span className="text-muted-foreground text-sm">{label}</span>
409
+ <span className={`${mono ? "font-mono" : ""} truncate text-sm`}>{value}</span>
410
+ </div>
411
+ );
412
+ }
@@ -0,0 +1 @@
1
+ {"_format":"","paths":{"artifacts":"out","build_infos":"out/build-info","sources":"src","tests":"test","scripts":"script","libraries":["lib"]},"files":{"src/AvaKitMessenger.sol":{"lastModificationDate":1782927411629,"contentHash":"f62fa8345d09a4e8","interfaceReprHash":null,"sourceName":"src/AvaKitMessenger.sol","imports":[],"versionRequirement":"^0.8.25","artifacts":{"AvaKitMessenger":{"0.8.28":{"default":{"path":"AvaKitMessenger.sol/AvaKitMessenger.json","build_id":"790b55b96be74f23"}}},"ITeleporterMessenger":{"0.8.28":{"default":{"path":"AvaKitMessenger.sol/ITeleporterMessenger.json","build_id":"790b55b96be74f23"}}},"ITeleporterReceiver":{"0.8.28":{"default":{"path":"AvaKitMessenger.sol/ITeleporterReceiver.json","build_id":"790b55b96be74f23"}}}},"seenByCompiler":true}},"builds":["790b55b96be74f23"],"profiles":{"default":{"solc":{"optimizer":{"enabled":true,"runs":200},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"outputSelection":{"*":{"*":["abi","evm.bytecode.object","evm.bytecode.sourceMap","evm.bytecode.linkReferences","evm.deployedBytecode.object","evm.deployedBytecode.sourceMap","evm.deployedBytecode.linkReferences","evm.deployedBytecode.immutableReferences","evm.methodIdentifiers","metadata"]}},"evmVersion":"osaka","viaIR":false,"libraries":{}},"vyper":{"evmVersion":"osaka","outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode"]}}}}},"preprocessed":false,"mocks":[]}
@@ -0,0 +1,6 @@
1
+ [profile.default]
2
+ src = "src"
3
+ out = "out"
4
+ libs = ["lib"]
5
+ optimizer = true
6
+ optimizer_runs = 200
@@ -0,0 +1 @@
1
+ {"abi":[{"type":"function","name":"TELEPORTER","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ITeleporterMessenger"}],"stateMutability":"view"},{"type":"function","name":"lastMessage","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"lastOriginSender","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"lastSourceBlockchainID","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"messagesReceived","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"receiveTeleporterMessage","inputs":[{"name":"sourceBlockchainID","type":"bytes32","internalType":"bytes32"},{"name":"originSenderAddress","type":"address","internalType":"address"},{"name":"message","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"sendMessage","inputs":[{"name":"destinationBlockchainID","type":"bytes32","internalType":"bytes32"},{"name":"destinationAddress","type":"address","internalType":"address"},{"name":"message","type":"string","internalType":"string"}],"outputs":[{"name":"messageID","type":"bytes32","internalType":"bytes32"}],"stateMutability":"nonpayable"},{"type":"event","name":"MessageReceived","inputs":[{"name":"sourceBlockchainID","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"originSender","type":"address","indexed":true,"internalType":"address"},{"name":"message","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"MessageSent","inputs":[{"name":"messageID","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"destinationBlockchainID","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"destinationAddress","type":"address","indexed":false,"internalType":"address"},{"name":"message","type":"string","indexed":false,"internalType":"string"}],"anonymous":false}],"bytecode":{"object":"0x6080604052348015600e575f5ffd5b506108f08061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061007a575f3560e01c80635be63c71116100585780635be63c71146100e4578063813275bc146100ed578063c0207bb814610108578063c868efaa14610111575f5ffd5b8063103070051461007e5780632ed2e8e0146100ae57806332970710146100cf575b5f5ffd5b600254610091906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100c16100bc3660046104aa565b610126565b6040519081526020016100a5565b6100d76102a6565b6040516100a5919061052e565b6100c160035481565b61009173253b2784c75e510dd0ff1da844684a1ac0aa5fcf81565b6100c160015481565b61012461011f3660046104aa565b610331565b005b5f73253b2784c75e510dd0ff1da844684a1ac0aa5fcf6001600160a01b031663624488506040518060c00160405280888152602001876001600160a01b0316815260200160405180604001604052805f6001600160a01b031681526020015f81525081526020016203d09081526020015f67ffffffffffffffff8111156101af576101af610547565b6040519080825280602002602001820160405280156101d8578160200160208202803683370190505b50815260200186866040516020016101f1929190610583565b6040516020818303038152906040528152506040518263ffffffff1660e01b815260040161021f91906105e1565b6020604051808303815f875af115801561023b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061025f9190610668565b905084817f4c6ebdf8689746d81e856c78d4049f7c9ae732786dd632398e24775ade8f62748686866040516102969392919061067f565b60405180910390a3949350505050565b5f80546102b2906106a3565b80601f01602080910402602001604051908101604052809291908181526020018280546102de906106a3565b80156103295780601f1061030057610100808354040283529160200191610329565b820191905f5260205f20905b81548152906001019060200180831161030c57829003601f168201915b505050505081565b3373253b2784c75e510dd0ff1da844684a1ac0aa5fcf146103ae5760405162461bcd60e51b815260206004820152602d60248201527f4176614b69744d657373656e6765723a2063616c6c6572206973206e6f74207460448201526c3432902a32b632b837b93a32b960991b606482015260840160405180910390fd5b5f6103bb828401846106db565b90505f6103c882826107da565b506001858155600280546001600160a01b0319166001600160a01b038716179055600380545f906103fa908490610895565b92505081905550836001600160a01b0316857fb668d57046ecd82ea44ba2a8fbfe10de34bec187561b8386394fed442e0de5468360405161043b919061052e565b60405180910390a35050505050565b80356001600160a01b0381168114610460575f5ffd5b919050565b5f5f83601f840112610475575f5ffd5b50813567ffffffffffffffff81111561048c575f5ffd5b6020830191508360208285010111156104a3575f5ffd5b9250929050565b5f5f5f5f606085870312156104bd575f5ffd5b843593506104cd6020860161044a565b9250604085013567ffffffffffffffff8111156104e8575f5ffd5b6104f487828801610465565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6105406020830184610500565b9392505050565b634e487b7160e01b5f52604160045260245ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f61059660208301848661055b565b949350505050565b5f8151808452602084019350602083015f5b828110156105d75781516001600160a01b03168652602095860195909101906001016105b0565b5093949350505050565b602081528151602082015260018060a01b0360208301511660408201525f604083015160018060a01b0381511660608401526020810151608084015250606083015160a0830152608083015160e060c084015261064261010084018261059e565b905060a0840151601f198483030160e085015261065f8282610500565b95945050505050565b5f60208284031215610678575f5ffd5b5051919050565b6001600160a01b03841681526040602082018190525f9061065f908301848661055b565b600181811c908216806106b757607f821691505b6020821081036106d557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156106eb575f5ffd5b813567ffffffffffffffff811115610701575f5ffd5b8201601f81018413610711575f5ffd5b803567ffffffffffffffff81111561072b5761072b610547565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561075a5761075a610547565b604052818152828201602001861015610771575f5ffd5b816020840160208301375f91810160200191909152949350505050565b601f8211156107d557805f5260205f20601f840160051c810160208510156107b35750805b601f840160051c820191505b818110156107d2575f81556001016107bf565b50505b505050565b815167ffffffffffffffff8111156107f4576107f4610547565b6108088161080284546106a3565b8461078e565b6020601f82116001811461083a575f83156108235750848201515b5f19600385901b1c1916600184901b1784556107d2565b5f84815260208120601f198516915b828110156108695787850151825560209485019460019092019101610849565b508482101561088657868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156108b457634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220edd28d4270dcbf530c3f8f54e0b5659e1f054d971e767fac9a41dbc42de8ada264736f6c634300081c0033","sourceMap":"1255:2468:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b506004361061007a575f3560e01c80635be63c71116100585780635be63c71146100e4578063813275bc146100ed578063c0207bb814610108578063c868efaa14610111575f5ffd5b8063103070051461007e5780632ed2e8e0146100ae57806332970710146100cf575b5f5ffd5b600254610091906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100c16100bc3660046104aa565b610126565b6040519081526020016100a5565b6100d76102a6565b6040516100a5919061052e565b6100c160035481565b61009173253b2784c75e510dd0ff1da844684a1ac0aa5fcf81565b6100c160015481565b61012461011f3660046104aa565b610331565b005b5f73253b2784c75e510dd0ff1da844684a1ac0aa5fcf6001600160a01b031663624488506040518060c00160405280888152602001876001600160a01b0316815260200160405180604001604052805f6001600160a01b031681526020015f81525081526020016203d09081526020015f67ffffffffffffffff8111156101af576101af610547565b6040519080825280602002602001820160405280156101d8578160200160208202803683370190505b50815260200186866040516020016101f1929190610583565b6040516020818303038152906040528152506040518263ffffffff1660e01b815260040161021f91906105e1565b6020604051808303815f875af115801561023b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061025f9190610668565b905084817f4c6ebdf8689746d81e856c78d4049f7c9ae732786dd632398e24775ade8f62748686866040516102969392919061067f565b60405180910390a3949350505050565b5f80546102b2906106a3565b80601f01602080910402602001604051908101604052809291908181526020018280546102de906106a3565b80156103295780601f1061030057610100808354040283529160200191610329565b820191905f5260205f20905b81548152906001019060200180831161030c57829003601f168201915b505050505081565b3373253b2784c75e510dd0ff1da844684a1ac0aa5fcf146103ae5760405162461bcd60e51b815260206004820152602d60248201527f4176614b69744d657373656e6765723a2063616c6c6572206973206e6f74207460448201526c3432902a32b632b837b93a32b960991b606482015260840160405180910390fd5b5f6103bb828401846106db565b90505f6103c882826107da565b506001858155600280546001600160a01b0319166001600160a01b038716179055600380545f906103fa908490610895565b92505081905550836001600160a01b0316857fb668d57046ecd82ea44ba2a8fbfe10de34bec187561b8386394fed442e0de5468360405161043b919061052e565b60405180910390a35050505050565b80356001600160a01b0381168114610460575f5ffd5b919050565b5f5f83601f840112610475575f5ffd5b50813567ffffffffffffffff81111561048c575f5ffd5b6020830191508360208285010111156104a3575f5ffd5b9250929050565b5f5f5f5f606085870312156104bd575f5ffd5b843593506104cd6020860161044a565b9250604085013567ffffffffffffffff8111156104e8575f5ffd5b6104f487828801610465565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6105406020830184610500565b9392505050565b634e487b7160e01b5f52604160045260245ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f61059660208301848661055b565b949350505050565b5f8151808452602084019350602083015f5b828110156105d75781516001600160a01b03168652602095860195909101906001016105b0565b5093949350505050565b602081528151602082015260018060a01b0360208301511660408201525f604083015160018060a01b0381511660608401526020810151608084015250606083015160a0830152608083015160e060c084015261064261010084018261059e565b905060a0840151601f198483030160e085015261065f8282610500565b95945050505050565b5f60208284031215610678575f5ffd5b5051919050565b6001600160a01b03841681526040602082018190525f9061065f908301848661055b565b600181811c908216806106b757607f821691505b6020821081036106d557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156106eb575f5ffd5b813567ffffffffffffffff811115610701575f5ffd5b8201601f81018413610711575f5ffd5b803567ffffffffffffffff81111561072b5761072b610547565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561075a5761075a610547565b604052818152828201602001861015610771575f5ffd5b816020840160208301375f91810160200191909152949350505050565b601f8211156107d557805f5260205f20601f840160051c810160208510156107b35750805b601f840160051c820191505b818110156107d2575f81556001016107bf565b50505b505050565b815167ffffffffffffffff8111156107f4576107f4610547565b6108088161080284546106a3565b8461078e565b6020601f82116001811461083a575f83156108235750848201515b5f19600385901b1c1916600184901b1784556107d2565b5f84815260208120601f198516915b828110156108695787850151825560209485019460019092019101610849565b508482101561088657868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156108b457634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220edd28d4270dcbf530c3f8f54e0b5659e1f054d971e767fac9a41dbc42de8ada264736f6c634300081c0033","sourceMap":"1255:2468:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1627:31;;;;;-1:-1:-1;;;;;1627:31:0;;;;;;-1:-1:-1;;;;;178:32:1;;;160:51;;148:2;133:18;1627:31:0;;;;;;;;2324:743;;;;;;:::i;:::-;;:::i;:::-;;;1503:25:1;;;1491:2;1476:18;2324:743:0;1357:177:1;1553:25:0;;;:::i;:::-;;;;;;;:::i;1664:31::-;;;;;;1424:122;;1503:42;1424:122;;1584:37;;;;;;3153:568;;;;;;:::i;:::-;;:::i;:::-;;2324:743;2479:17;1503:42;-1:-1:-1;;;;;2520:32:0;;2566:393;;;;;;;;2632:23;2566:393;;;;2693:18;-1:-1:-1;;;;;2566:393:0;;;;;2738:59;;;;;;;;2782:1;-1:-1:-1;;;;;2738:59:0;;;;;2794:1;2738:59;;;2566:393;;;;2833:6;2566:393;;;;2896:1;2882:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2882:16:0;;2566:393;;;;2936:7;;2925:19;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2566:393;;;2520:449;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2508:461;;3007:23;2996:9;2984:76;3032:18;3052:7;;2984:76;;;;;;;;:::i;:::-;;;;;;;;2324:743;;;;;;:::o;1553:25::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3153:568::-;3325:10;1503:42;3325:33;3317:91;;;;-1:-1:-1;;;3317:91:0;;6294:2:1;3317:91:0;;;6276:21:1;6333:2;6313:18;;;6306:30;6372:34;6352:18;;;6345:62;-1:-1:-1;;;6423:18:1;;;6416:43;6476:19;;3317:91:0;;;;;;;;3418:21;3442:29;;;;3453:7;3442:29;:::i;:::-;3418:53;-1:-1:-1;3481:11:0;:21;3418:53;3481:11;:21;:::i;:::-;-1:-1:-1;3512:22:0;:43;;;3565:16;:38;;-1:-1:-1;;;;;;3565:38:0;-1:-1:-1;;;;;3565:38:0;;;;;3613:16;:21;;-1:-1:-1;;3613:21:0;;3512:22;;3613:21;:::i;:::-;;;;;;;;3685:19;-1:-1:-1;;;;;3649:65:0;3665:18;3649:65;3706:7;3649:65;;;;;;:::i;:::-;;;;;;;;3307:414;3153:568;;;;:::o;222:173:1:-;290:20;;-1:-1:-1;;;;;339:31:1;;329:42;;319:70;;385:1;382;375:12;319:70;222:173;;;:::o;400:348::-;452:8;462:6;516:3;509:4;501:6;497:17;493:27;483:55;;534:1;531;524:12;483:55;-1:-1:-1;557:20:1;;600:18;589:30;;586:50;;;632:1;629;622:12;586:50;669:4;661:6;657:17;645:29;;721:3;714:4;705:6;697;693:19;689:30;686:39;683:59;;;738:1;735;728:12;683:59;400:348;;;;;:::o;753:599::-;842:6;850;858;866;919:2;907:9;898:7;894:23;890:32;887:52;;;935:1;932;925:12;887:52;980:23;;;-1:-1:-1;1046:38:1;1080:2;1065:18;;1046:38;:::i;:::-;1036:48;;1135:2;1124:9;1120:18;1107:32;1162:18;1154:6;1151:30;1148:50;;;1194:1;1191;1184:12;1148:50;1233:59;1284:7;1275:6;1264:9;1260:22;1233:59;:::i;:::-;753:599;;;;-1:-1:-1;1311:8:1;-1:-1:-1;;;;753:599:1:o;1539:289::-;1581:3;1619:5;1613:12;1646:6;1641:3;1634:19;1702:6;1695:4;1688:5;1684:16;1677:4;1672:3;1668:14;1662:47;1754:1;1747:4;1738:6;1733:3;1729:16;1725:27;1718:38;1817:4;1810:2;1806:7;1801:2;1793:6;1789:15;1785:29;1780:3;1776:39;1772:50;1765:57;;;1539:289;;;;:::o;1833:220::-;1982:2;1971:9;1964:21;1945:4;2002:45;2043:2;2032:9;2028:18;2020:6;2002:45;:::i;:::-;1994:53;1833:220;-1:-1:-1;;;1833:220:1:o;3078:127::-;3139:10;3134:3;3130:20;3127:1;3120:31;3170:4;3167:1;3160:15;3194:4;3191:1;3184:15;3210:267;3299:6;3294:3;3287:19;3351:6;3344:5;3337:4;3332:3;3328:14;3315:43;-1:-1:-1;3403:1:1;3378:16;;;3396:4;3374:27;;;3367:38;;;;3459:2;3438:15;;;-1:-1:-1;;3434:29:1;3425:39;;;3421:50;;3210:267::o;3482:247::-;3641:2;3630:9;3623:21;3604:4;3661:62;3719:2;3708:9;3704:18;3696:6;3688;3661:62;:::i;:::-;3653:70;3482:247;-1:-1:-1;;;;3482:247:1:o;3734:446::-;3787:3;3825:5;3819:12;3852:6;3847:3;3840:19;3884:4;3879:3;3875:14;3868:21;;3923:4;3916:5;3912:16;3946:1;3956:199;3970:6;3967:1;3964:13;3956:199;;;4035:13;;-1:-1:-1;;;;;4031:39:1;4019:52;;4100:4;4091:14;;;;4128:17;;;;4067:1;3985:9;3956:199;;;-1:-1:-1;4171:3:1;;3734:446;-1:-1:-1;;;;3734:446:1:o;4185:979::-;4390:2;4379:9;4372:21;4435:6;4429:13;4424:2;4413:9;4409:18;4402:41;4524:1;4520;4515:3;4511:11;4507:19;4501:2;4493:6;4489:15;4483:22;4479:48;4474:2;4463:9;4459:18;4452:76;4353:4;4575:2;4567:6;4563:15;4557:22;4657:1;4653;4648:3;4644:11;4640:19;4625:12;4619:19;4615:45;4610:2;4599:9;4595:18;4588:73;4722:2;4708:12;4704:21;4698:28;4692:3;4681:9;4677:19;4670:57;;4782:2;4774:6;4770:15;4764:22;4758:3;4747:9;4743:19;4736:51;4836:3;4828:6;4824:16;4818:23;4878:4;4872:3;4861:9;4857:19;4850:33;4906:65;4966:3;4955:9;4951:19;4935:14;4906:65;:::i;:::-;4892:79;;5020:3;5012:6;5008:16;5002:23;5095:2;5091:7;5079:9;5071:6;5067:22;5063:36;5056:4;5045:9;5041:20;5034:66;5117:41;5151:6;5135:14;5117:41;:::i;:::-;5109:49;4185:979;-1:-1:-1;;;;;4185:979:1:o;5169:184::-;5239:6;5292:2;5280:9;5271:7;5267:23;5263:32;5260:52;;;5308:1;5305;5298:12;5260:52;-1:-1:-1;5331:16:1;;5169:184;-1:-1:-1;5169:184:1:o;5358:344::-;-1:-1:-1;;;;;5545:32:1;;5527:51;;5614:2;5609;5594:18;;5587:30;;;-1:-1:-1;;5634:62:1;;5677:18;;5669:6;5661;5634:62;:::i;5707:380::-;5786:1;5782:12;;;;5829;;;5850:61;;5904:4;5896:6;5892:17;5882:27;;5850:61;5957:2;5949:6;5946:14;5926:18;5923:38;5920:161;;6003:10;5998:3;5994:20;5991:1;5984:31;6038:4;6035:1;6028:15;6066:4;6063:1;6056:15;5920:161;;5707:380;;;:::o;6506:945::-;6575:6;6628:2;6616:9;6607:7;6603:23;6599:32;6596:52;;;6644:1;6641;6634:12;6596:52;6684:9;6671:23;6717:18;6709:6;6706:30;6703:50;;;6749:1;6746;6739:12;6703:50;6772:22;;6825:4;6817:13;;6813:27;-1:-1:-1;6803:55:1;;6854:1;6851;6844:12;6803:55;6894:2;6881:16;6920:18;6912:6;6909:30;6906:56;;;6942:18;;:::i;:::-;6991:2;6985:9;7083:2;7045:17;;-1:-1:-1;;7041:31:1;;;7074:2;7037:40;7033:54;7021:67;;7118:18;7103:34;;7139:22;;;7100:62;7097:88;;;7165:18;;:::i;:::-;7201:2;7194:22;7225;;;7266:15;;;7283:2;7262:24;7259:37;-1:-1:-1;7256:57:1;;;7309:1;7306;7299:12;7256:57;7365:6;7360:2;7356;7352:11;7347:2;7339:6;7335:15;7322:50;7418:1;7392:19;;;7413:2;7388:28;7381:39;;;;7396:6;6506:945;-1:-1:-1;;;;6506:945:1:o;7582:518::-;7684:2;7679:3;7676:11;7673:421;;;7720:5;7717:1;7710:16;7764:4;7761:1;7751:18;7834:2;7822:10;7818:19;7815:1;7811:27;7805:4;7801:38;7870:4;7858:10;7855:20;7852:47;;;-1:-1:-1;7893:4:1;7852:47;7948:2;7943:3;7939:12;7936:1;7932:20;7926:4;7922:31;7912:41;;8003:81;8021:2;8014:5;8011:13;8003:81;;;8080:1;8066:16;;8047:1;8036:13;8003:81;;;8007:3;;7673:421;7582:518;;;:::o;8276:1299::-;8402:3;8396:10;8429:18;8421:6;8418:30;8415:56;;;8451:18;;:::i;:::-;8480:97;8570:6;8530:38;8562:4;8556:11;8530:38;:::i;:::-;8524:4;8480:97;:::i;:::-;8626:4;8657:2;8646:14;;8674:1;8669:649;;;;9362:1;9379:6;9376:89;;;-1:-1:-1;9431:19:1;;;9425:26;9376:89;-1:-1:-1;;8233:1:1;8229:11;;;8225:24;8221:29;8211:40;8257:1;8253:11;;;8208:57;9478:81;;8639:930;;8669:649;7529:1;7522:14;;;7566:4;7553:18;;-1:-1:-1;;8705:20:1;;;8823:222;8837:7;8834:1;8831:14;8823:222;;;8919:19;;;8913:26;8898:42;;9026:4;9011:20;;;;8979:1;8967:14;;;;8853:12;8823:222;;;8827:3;9073:6;9064:7;9061:19;9058:201;;;9134:19;;;9128:26;-1:-1:-1;;9217:1:1;9213:14;;;9229:3;9209:24;9205:37;9201:42;9186:58;9171:74;;9058:201;-1:-1:-1;;;;9305:1:1;9289:14;;;9285:22;9272:36;;-1:-1:-1;8276:1299:1:o;9580:222::-;9645:9;;;9666:10;;;9663:133;;;9718:10;9713:3;9709:20;9706:1;9699:31;9753:4;9750:1;9743:15;9781:4;9778:1;9771:15;9663:133;9580:222;;;;:::o","linkReferences":{}},"methodIdentifiers":{"TELEPORTER()":"813275bc","lastMessage()":"32970710","lastOriginSender()":"10307005","lastSourceBlockchainID()":"c0207bb8","messagesReceived()":"5be63c71","receiveTeleporterMessage(bytes32,address,bytes)":"c868efaa","sendMessage(bytes32,address,string)":"2ed2e8e0"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"MessageReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"TELEPORTER\",\"outputs\":[{\"internalType\":\"contract ITeleporterMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMessage\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastOriginSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastSourceBlockchainID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messagesReceived\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"originSenderAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"receiveTeleporterMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"sendMessage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageID\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"sendMessage(bytes32,address,string)\":{\"params\":{\"destinationAddress\":\"The AvaKitMessenger address on the destination L1.\",\"destinationBlockchainID\":\"The destination L1's blockchain ID \\u2014 a bytes32, NOT an EVM chainId. Get it from `avalanche blockchain describe`.\"}}},\"title\":\"AvaKitMessenger \\u2014 a cross-chain message board over Avalanche ICM.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"TELEPORTER()\":{\"notice\":\"The TeleporterMessenger predeploy, at the same fixed address on every ICM-enabled Avalanche chain.\"},\"receiveTeleporterMessage(bytes32,address,bytes)\":{\"notice\":\"Called by the local TeleporterMessenger when a message arrives.\"},\"sendMessage(bytes32,address,string)\":{\"notice\":\"Send `message` to an AvaKitMessenger on another Avalanche L1.\"}},\"notice\":\"Deploy the same contract on two Avalanche L1s. Sending a string from one L1 delivers it to the contract on the other L1 via Interchain Messaging; the relayer carries the message and calls `receiveTeleporterMessage`.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/AvaKitMessenger.sol\":\"AvaKitMessenger\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/AvaKitMessenger.sol\":{\"keccak256\":\"0x2b5bbe26f504a40e93e62e676fb993e4c58a1ddf541e7f26b3987d8e6237fbce\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33fb058ae81fea833bdfb158ebba6454b99fabd9b9259a125f70b7535f1df981\",\"dweb:/ipfs/QmWcawkhzMgmuduVyRrYbwruXDeRsQf6pLHdqjxC5LMZSy\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"bytes32","name":"sourceBlockchainID","type":"bytes32","indexed":true},{"internalType":"address","name":"originSender","type":"address","indexed":true},{"internalType":"string","name":"message","type":"string","indexed":false}],"type":"event","name":"MessageReceived","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"messageID","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"destinationBlockchainID","type":"bytes32","indexed":true},{"internalType":"address","name":"destinationAddress","type":"address","indexed":false},{"internalType":"string","name":"message","type":"string","indexed":false}],"type":"event","name":"MessageSent","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"TELEPORTER","outputs":[{"internalType":"contract ITeleporterMessenger","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"lastMessage","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"lastOriginSender","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"lastSourceBlockchainID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"messagesReceived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"bytes32","name":"sourceBlockchainID","type":"bytes32"},{"internalType":"address","name":"originSenderAddress","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"receiveTeleporterMessage"},{"inputs":[{"internalType":"bytes32","name":"destinationBlockchainID","type":"bytes32"},{"internalType":"address","name":"destinationAddress","type":"address"},{"internalType":"string","name":"message","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"sendMessage","outputs":[{"internalType":"bytes32","name":"messageID","type":"bytes32"}]}],"devdoc":{"kind":"dev","methods":{"sendMessage(bytes32,address,string)":{"params":{"destinationAddress":"The AvaKitMessenger address on the destination L1.","destinationBlockchainID":"The destination L1's blockchain ID — a bytes32, NOT an EVM chainId. Get it from `avalanche blockchain describe`."}}},"version":1},"userdoc":{"kind":"user","methods":{"TELEPORTER()":{"notice":"The TeleporterMessenger predeploy, at the same fixed address on every ICM-enabled Avalanche chain."},"receiveTeleporterMessage(bytes32,address,bytes)":{"notice":"Called by the local TeleporterMessenger when a message arrives."},"sendMessage(bytes32,address,string)":{"notice":"Send `message` to an AvaKitMessenger on another Avalanche L1."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/AvaKitMessenger.sol":"AvaKitMessenger"},"evmVersion":"prague","libraries":{}},"sources":{"src/AvaKitMessenger.sol":{"keccak256":"0x2b5bbe26f504a40e93e62e676fb993e4c58a1ddf541e7f26b3987d8e6237fbce","urls":["bzz-raw://33fb058ae81fea833bdfb158ebba6454b99fabd9b9259a125f70b7535f1df981","dweb:/ipfs/QmWcawkhzMgmuduVyRrYbwruXDeRsQf6pLHdqjxC5LMZSy"],"license":"MIT"}},"version":1},"id":0}
@@ -0,0 +1 @@
1
+ {"abi":[{"type":"function","name":"sendCrossChainMessage","inputs":[{"name":"messageInput","type":"tuple","internalType":"struct TeleporterMessageInput","components":[{"name":"destinationBlockchainID","type":"bytes32","internalType":"bytes32"},{"name":"destinationAddress","type":"address","internalType":"address"},{"name":"feeInfo","type":"tuple","internalType":"struct TeleporterFeeInfo","components":[{"name":"feeTokenAddress","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}]},{"name":"requiredGasLimit","type":"uint256","internalType":"uint256"},{"name":"allowedRelayerAddresses","type":"address[]","internalType":"address[]"},{"name":"message","type":"bytes","internalType":"bytes"}]}],"outputs":[{"name":"messageID","type":"bytes32","internalType":"bytes32"}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"sendCrossChainMessage((bytes32,address,(address,uint256),uint256,address[],bytes))":"62448850"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"destinationBlockchainID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct TeleporterFeeInfo\",\"name\":\"feeInfo\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"requiredGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"allowedRelayerAddresses\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"internalType\":\"struct TeleporterMessageInput\",\"name\":\"messageInput\",\"type\":\"tuple\"}],\"name\":\"sendCrossChainMessage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageID\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/AvaKitMessenger.sol\":\"ITeleporterMessenger\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/AvaKitMessenger.sol\":{\"keccak256\":\"0x2b5bbe26f504a40e93e62e676fb993e4c58a1ddf541e7f26b3987d8e6237fbce\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33fb058ae81fea833bdfb158ebba6454b99fabd9b9259a125f70b7535f1df981\",\"dweb:/ipfs/QmWcawkhzMgmuduVyRrYbwruXDeRsQf6pLHdqjxC5LMZSy\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct TeleporterMessageInput","name":"messageInput","type":"tuple","components":[{"internalType":"bytes32","name":"destinationBlockchainID","type":"bytes32"},{"internalType":"address","name":"destinationAddress","type":"address"},{"internalType":"struct TeleporterFeeInfo","name":"feeInfo","type":"tuple","components":[{"internalType":"address","name":"feeTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}]},{"internalType":"uint256","name":"requiredGasLimit","type":"uint256"},{"internalType":"address[]","name":"allowedRelayerAddresses","type":"address[]"},{"internalType":"bytes","name":"message","type":"bytes"}]}],"stateMutability":"nonpayable","type":"function","name":"sendCrossChainMessage","outputs":[{"internalType":"bytes32","name":"messageID","type":"bytes32"}]}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/AvaKitMessenger.sol":"ITeleporterMessenger"},"evmVersion":"prague","libraries":{}},"sources":{"src/AvaKitMessenger.sol":{"keccak256":"0x2b5bbe26f504a40e93e62e676fb993e4c58a1ddf541e7f26b3987d8e6237fbce","urls":["bzz-raw://33fb058ae81fea833bdfb158ebba6454b99fabd9b9259a125f70b7535f1df981","dweb:/ipfs/QmWcawkhzMgmuduVyRrYbwruXDeRsQf6pLHdqjxC5LMZSy"],"license":"MIT"}},"version":1},"id":0}
@@ -0,0 +1 @@
1
+ {"abi":[{"type":"function","name":"receiveTeleporterMessage","inputs":[{"name":"sourceBlockchainID","type":"bytes32","internalType":"bytes32"},{"name":"originSenderAddress","type":"address","internalType":"address"},{"name":"message","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"receiveTeleporterMessage(bytes32,address,bytes)":"c868efaa"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sourceBlockchainID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"originSenderAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"receiveTeleporterMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/AvaKitMessenger.sol\":\"ITeleporterReceiver\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/AvaKitMessenger.sol\":{\"keccak256\":\"0x2b5bbe26f504a40e93e62e676fb993e4c58a1ddf541e7f26b3987d8e6237fbce\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33fb058ae81fea833bdfb158ebba6454b99fabd9b9259a125f70b7535f1df981\",\"dweb:/ipfs/QmWcawkhzMgmuduVyRrYbwruXDeRsQf6pLHdqjxC5LMZSy\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"bytes32","name":"sourceBlockchainID","type":"bytes32"},{"internalType":"address","name":"originSenderAddress","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"receiveTeleporterMessage"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/AvaKitMessenger.sol":"ITeleporterReceiver"},"evmVersion":"prague","libraries":{}},"sources":{"src/AvaKitMessenger.sol":{"keccak256":"0x2b5bbe26f504a40e93e62e676fb993e4c58a1ddf541e7f26b3987d8e6237fbce","urls":["bzz-raw://33fb058ae81fea833bdfb158ebba6454b99fabd9b9259a125f70b7535f1df981","dweb:/ipfs/QmWcawkhzMgmuduVyRrYbwruXDeRsQf6pLHdqjxC5LMZSy"],"license":"MIT"}},"version":1},"id":0}
@@ -0,0 +1 @@
1
+ {"id":"790b55b96be74f23","source_id_to_path":{"0":"src/AvaKitMessenger.sol"},"language":"Solidity"}
@@ -0,0 +1,97 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.25;
3
+
4
+ // Minimal Avalanche Interchain Messaging (ICM / Teleporter) interfaces, inlined
5
+ // so this contract compiles with no external dependencies. The full contracts
6
+ // live at https://github.com/ava-labs/icm-contracts.
7
+
8
+ struct TeleporterFeeInfo {
9
+ address feeTokenAddress;
10
+ uint256 amount;
11
+ }
12
+
13
+ struct TeleporterMessageInput {
14
+ bytes32 destinationBlockchainID;
15
+ address destinationAddress;
16
+ TeleporterFeeInfo feeInfo;
17
+ uint256 requiredGasLimit;
18
+ address[] allowedRelayerAddresses;
19
+ bytes message;
20
+ }
21
+
22
+ interface ITeleporterMessenger {
23
+ function sendCrossChainMessage(TeleporterMessageInput calldata messageInput)
24
+ external
25
+ returns (bytes32 messageID);
26
+ }
27
+
28
+ interface ITeleporterReceiver {
29
+ function receiveTeleporterMessage(
30
+ bytes32 sourceBlockchainID,
31
+ address originSenderAddress,
32
+ bytes calldata message
33
+ ) external;
34
+ }
35
+
36
+ /// @title AvaKitMessenger — a cross-chain message board over Avalanche ICM.
37
+ /// @notice Deploy the same contract on two Avalanche L1s. Sending a string from
38
+ /// one L1 delivers it to the contract on the other L1 via Interchain Messaging;
39
+ /// the relayer carries the message and calls `receiveTeleporterMessage`.
40
+ contract AvaKitMessenger is ITeleporterReceiver {
41
+ /// The TeleporterMessenger predeploy, at the same fixed address on every
42
+ /// ICM-enabled Avalanche chain.
43
+ ITeleporterMessenger public constant TELEPORTER =
44
+ ITeleporterMessenger(0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf);
45
+
46
+ string public lastMessage;
47
+ bytes32 public lastSourceBlockchainID;
48
+ address public lastOriginSender;
49
+ uint256 public messagesReceived;
50
+
51
+ event MessageSent(
52
+ bytes32 indexed messageID,
53
+ bytes32 indexed destinationBlockchainID,
54
+ address destinationAddress,
55
+ string message
56
+ );
57
+ event MessageReceived(
58
+ bytes32 indexed sourceBlockchainID, address indexed originSender, string message
59
+ );
60
+
61
+ /// @notice Send `message` to an AvaKitMessenger on another Avalanche L1.
62
+ /// @param destinationBlockchainID The destination L1's blockchain ID — a
63
+ /// bytes32, NOT an EVM chainId. Get it from `avalanche blockchain describe`.
64
+ /// @param destinationAddress The AvaKitMessenger address on the destination L1.
65
+ function sendMessage(
66
+ bytes32 destinationBlockchainID,
67
+ address destinationAddress,
68
+ string calldata message
69
+ ) external returns (bytes32 messageID) {
70
+ messageID = TELEPORTER.sendCrossChainMessage(
71
+ TeleporterMessageInput({
72
+ destinationBlockchainID: destinationBlockchainID,
73
+ destinationAddress: destinationAddress,
74
+ feeInfo: TeleporterFeeInfo({feeTokenAddress: address(0), amount: 0}),
75
+ requiredGasLimit: 250000,
76
+ allowedRelayerAddresses: new address[](0),
77
+ message: abi.encode(message)
78
+ })
79
+ );
80
+ emit MessageSent(messageID, destinationBlockchainID, destinationAddress, message);
81
+ }
82
+
83
+ /// @notice Called by the local TeleporterMessenger when a message arrives.
84
+ function receiveTeleporterMessage(
85
+ bytes32 sourceBlockchainID,
86
+ address originSenderAddress,
87
+ bytes calldata message
88
+ ) external {
89
+ require(msg.sender == address(TELEPORTER), "AvaKitMessenger: caller is not the Teleporter");
90
+ string memory decoded = abi.decode(message, (string));
91
+ lastMessage = decoded;
92
+ lastSourceBlockchainID = sourceBlockchainID;
93
+ lastOriginSender = originSenderAddress;
94
+ messagesReceived += 1;
95
+ emit MessageReceived(sourceBlockchainID, originSenderAddress, decoded);
96
+ }
97
+ }
@@ -0,0 +1,32 @@
1
+ ---
2
+ description: AvaKit + Avalanche NFT conventions for this project
3
+ globs: ["**/*.ts", "**/*.tsx", "**/*.sol", "**/*.css"]
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # AvaKit NFT project rules
8
+
9
+ This is an Avalanche NFT dapp built with AvaKit. It deploys an ERC-721 from the browser, then mints.
10
+
11
+ ## Flow
12
+
13
+ - Deploy: `useAvaDeploy().deploy({ abi, bytecode })` (artifact in `lib/nft-artifact.ts`).
14
+ - Mint: `useContract({ address, abi }).write("mint", [])`.
15
+ - Read: `.read("totalSupply")`, `.read("balanceOf", [address])`.
16
+
17
+ ## Contract
18
+
19
+ - Source: `contracts/src/AvaKitNFT.sol` (minimal, self-contained ERC-721 — no external deps).
20
+ - After editing, recompile: `cd contracts && forge build`, then update `lib/nft-artifact.ts` with the new abi + bytecode.object.
21
+
22
+ ## UI
23
+
24
+ - shadcn/ui only; `@avakit/react` components are shadcn-styled.
25
+ - Black & white only for now; dark/light via next-themes; both must work.
26
+ - Animations: Framer Motion or GSAP only.
27
+
28
+ ## Safety
29
+
30
+ - Deploying and minting cost gas — fund the wallet on Fuji first.
31
+ - Default chain is Fuji testnet; mainnet requires explicit opt-in.
32
+ - Never hardcode secrets; keys stay in the wallet provider.