@stage-labs/metro 0.1.0-beta.250 → 0.1.0-beta.251
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metro",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.251",
|
|
4
4
|
"description": "Metro for Claude Code, installed by the metro daemon on this machine: every connector the agent holds as its own MCP server relayed through the daemon, the orchestrator-only guard on the main thread, and the standing rules loaded at each session start. No vendor credential ever sits in a config file.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Bonustrack",
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
type ProfileChange,
|
|
12
12
|
} from '@metro-labs/core/stations/profile';
|
|
13
13
|
import { accountForCall } from './accounts.js';
|
|
14
|
-
import { claimName, nameOf, parseLabel } from './names.js';
|
|
15
|
-
import { sendSponsored, type SmartAccount } from './smart.js';
|
|
14
|
+
import { STAGE_NAMES_PARENT, claimName, nameOf, parseLabel } from './names.js';
|
|
15
|
+
import { sendSponsored, sendSponsoredCalls, type SmartAccount, type SponsoredCall } from './smart.js';
|
|
16
16
|
import { respond } from '@metro-labs/core/stations/station-runtime';
|
|
17
17
|
|
|
18
18
|
export const BASENAME_REGISTRY = '0xB94704422c2a1E396835A571837Aa5AE53285a95' as const;
|
|
@@ -36,6 +36,7 @@ const RESOLVER_ABI = [
|
|
|
36
36
|
outputs: [],
|
|
37
37
|
},
|
|
38
38
|
{ name: 'multicall', type: 'function', stateMutability: 'nonpayable', inputs: [{ name: 'data', type: 'bytes[]' }], outputs: [{ name: 'results', type: 'bytes[]' }] },
|
|
39
|
+
{ name: 'setAddr', type: 'function', stateMutability: 'nonpayable', inputs: [{ name: 'node', type: 'bytes32' }, { name: 'a', type: 'address' }], outputs: [] },
|
|
39
40
|
] as const;
|
|
40
41
|
|
|
41
42
|
const REVERSE_ABI = [
|
|
@@ -70,9 +71,9 @@ export const encodePrimaryName = (name: string): Hex => encodeFunctionData({ abi
|
|
|
70
71
|
export const reverseNodeOf = (address: string): Hex =>
|
|
71
72
|
keccak256(encodePacked(['bytes32', 'bytes32'], [BASE_REVERSE_ROOT, keccak256(stringToBytes(address.slice(2).toLowerCase()))]));
|
|
72
73
|
|
|
73
|
-
async function resolverOf(smart: SmartAccount, node: Hex): Promise<Hex> {
|
|
74
|
+
async function resolverOf(smart: SmartAccount, node: Hex, fallback: Hex = BASENAME_L2_RESOLVER): Promise<Hex> {
|
|
74
75
|
const found: Hex = await smart.publicClient.readContract({ address: BASENAME_REGISTRY, abi: REGISTRY_ABI, functionName: 'resolver', args: [node] });
|
|
75
|
-
return found === ZERO ?
|
|
76
|
+
return found === ZERO ? fallback : found;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export async function primaryNameOf(smart: SmartAccount): Promise<string | null> {
|
|
@@ -81,12 +82,18 @@ export async function primaryNameOf(smart: SmartAccount): Promise<string | null>
|
|
|
81
82
|
return found === '' ? null : found;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
export
|
|
85
|
+
export function nameSetupCalls(name: string, address: Hex, resolver: Hex): SponsoredCall[] {
|
|
86
|
+
const setAddr = encodeFunctionData({ abi: RESOLVER_ABI, functionName: 'setAddr', args: [namehash(normalize(name)), address] });
|
|
87
|
+
return [{ to: resolver, data: setAddr }, { to: BASENAME_REVERSE_REGISTRAR, data: encodePrimaryName(name) }];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function setUpName(smart: SmartAccount, name: string): Promise<boolean> {
|
|
85
91
|
try {
|
|
86
|
-
await
|
|
92
|
+
const resolver = await resolverOf(smart, namehash(normalize(name)), await resolverOf(smart, namehash(STAGE_NAMES_PARENT)));
|
|
93
|
+
await sendSponsoredCalls(smart, nameSetupCalls(name, smart.address, resolver));
|
|
87
94
|
return true;
|
|
88
95
|
} catch (err) {
|
|
89
|
-
process.stderr.write(`xmtp: the name ${name} is claimed but
|
|
96
|
+
process.stderr.write(`xmtp: the name ${name} is claimed but its address and primary name are not set for ${smart.address}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
90
97
|
return false;
|
|
91
98
|
}
|
|
92
99
|
}
|
|
@@ -136,13 +143,13 @@ export async function claimNameAction(id: string, args: Args): Promise<void> {
|
|
|
136
143
|
const held = await nameOf(address);
|
|
137
144
|
if (held !== null) throw new TrainError('name_held', `this account already holds ${held}`);
|
|
138
145
|
const name = await claimName(parseLabel(args.label), address, (message) => smart.signMessage(message));
|
|
139
|
-
const primary = await
|
|
146
|
+
const primary = await setUpName(smart, name);
|
|
140
147
|
respond(id, { result: { account: accountId, name, primary } });
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
export async function ensurePrimaryName(smart: SmartAccount, name: string): Promise<boolean> {
|
|
144
151
|
if ((await primaryNameOf(smart)) === name) return true;
|
|
145
|
-
return
|
|
152
|
+
return setUpName(smart, name);
|
|
146
153
|
}
|
|
147
154
|
|
|
148
155
|
export async function nameAction(id: string, args: Args): Promise<void> {
|
|
@@ -57,14 +57,21 @@ export async function smartAccountFor(privateKey: string, rpc = zerodevRpc()): P
|
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
export
|
|
60
|
+
export interface SponsoredCall {
|
|
61
|
+
to: Hex;
|
|
62
|
+
data: Hex;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function sendSponsoredCalls(smart: SmartAccount, calls: SponsoredCall[]): Promise<Hex> {
|
|
61
66
|
const client = smart.client();
|
|
62
|
-
const hash = await client.sendTransaction({
|
|
67
|
+
const hash = await client.sendTransaction({ calls: calls.map((call) => ({ ...call, value: 0n })) });
|
|
63
68
|
const receipt = await smart.publicClient.waitForTransactionReceipt({ hash });
|
|
64
69
|
if (receipt.status !== 'success') throw new Error(`the Base transaction ${hash} reverted`);
|
|
65
70
|
return hash;
|
|
66
71
|
}
|
|
67
72
|
|
|
73
|
+
export const sendSponsored = (smart: SmartAccount, to: Hex, data: Hex): Promise<Hex> => sendSponsoredCalls(smart, [{ to, data }]);
|
|
74
|
+
|
|
68
75
|
export async function ensureDeployed(smart: SmartAccount): Promise<boolean> {
|
|
69
76
|
if (await smart.deployed()) return false;
|
|
70
77
|
await sendSponsored(smart, smart.address, '0x');
|
package/runtime/runtime.json
CHANGED