Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions app/src/panels/A12-config/ConfigPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Search, SlidersHorizontal, Upload } from 'lucide-react';
import { Panel } from '../../components/Panel';
import { useConfig, useSetConfig } from '../../hooks/useConfig';
import { usePontoonStore } from '../../state/store';
import type { ConfigParam } from '../../rpc/contract';
import {
Badge,
Button,
Expand All @@ -19,13 +20,6 @@ import {
TableRow
} from '../../components/ui';

type ConfigParam = {
id: number;
label?: string;
kind: 'labeled' | 'raw';
value: string | { boc: string };
};

export function ConfigPanel() {
const workspaceId = usePontoonStore((s) => s.activeWorkspaceId);
const query = useConfig(workspaceId);
Expand Down Expand Up @@ -70,7 +64,10 @@ function ConfigBody({ params, onSet, setPending }: BodyProps) {
(p) =>
String(p.id).includes(q) ||
(p.label ?? '').toLowerCase().includes(q) ||
valueString(p.value).toLowerCase().includes(q)
valueString(p.value).toLowerCase().includes(q) ||
(p.fields ?? []).some(
(f) => f.label.toLowerCase().includes(q) || f.value.toLowerCase().includes(q)
)
);
}, [params, filter]);

Expand Down Expand Up @@ -116,7 +113,9 @@ function ConfigBody({ params, onSet, setPending }: BodyProps) {
<TableBody>
{filtered.map((param) => {
const value = valueString(param.value);
const isBoc = typeof param.value !== 'string';
const copyValue = param.fields
? param.fields.map((f) => `${f.label}: ${f.value}`).join('\n')
: value;
return (
<TableRow key={param.id}>
<TableCell className="font-mono text-xs font-semibold text-foreground">
Expand All @@ -127,14 +126,27 @@ function ConfigBody({ params, onSet, setPending }: BodyProps) {
</TableCell>
<TableCell>
<Badge variant={param.kind === 'labeled' ? 'secondary' : 'outline'}>
{isBoc ? 'boc' : param.kind}
{param.kind}
</Badge>
</TableCell>
<TableCell className="max-w-[260px]">
<MonoValue value={value} />
<TableCell className="max-w-[280px]">
{param.fields ? (
<dl className="flex flex-col gap-1">
{param.fields.map((f) => (
<div key={f.label} className="flex items-baseline justify-between gap-3">
<dt className="text-xs text-muted-foreground">{f.label}</dt>
<dd>
<MonoValue value={f.value} />
</dd>
</div>
))}
</dl>
) : (
<MonoValue value={value} />
)}
</TableCell>
<TableCell className="pl-0">
<CopyButton value={value} className="size-6" />
<CopyButton value={copyValue} className="size-6" />
</TableCell>
</TableRow>
);
Expand Down
16 changes: 15 additions & 1 deletion app/src/rpc/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,20 @@ export interface SubscriptionResponse {
subscriptionId: string;
}

export interface DecodedConfigField {
label: string;
value: string;
}

export interface ConfigParam {
id: number;
label?: string;
kind: 'labeled' | 'raw';
value: string | { boc: string };
/** Decoded fields for labeled params (fee/gas/validator values); absent for raw params. */
fields?: DecodedConfigField[];
}

export type MethodMap = {
'handshake': { req: HandshakeRequest; res: HandshakeResponse };
'workspace.open': { req: { path: string }; res: WorkspaceRef };
Expand Down Expand Up @@ -294,7 +308,7 @@ export type MethodMap = {
'snapshot.export': { req: { workspaceId: string; id: string }; res: { boc: string } };
'snapshot.import': { req: { workspaceId: string; name: string; boc: string }; res: SnapshotRef };
'fork.status': { req: { workspaceId: string }; res: { enabled: boolean; mode: 'pinned-readonly'; network: 'mainnet' | 'testnet'; blockSeqno: number; accounts: { address: string; loaded: 'lazy' | 'cached'; overridden: boolean }[] } };
'config.get': { req: { workspaceId: string }; res: { params: { id: number; label?: string; kind: 'labeled' | 'raw'; value: string | { boc: string } }[] } };
'config.get': { req: { workspaceId: string }; res: { params: ConfigParam[] } };
'config.set': { req: { workspaceId: string; boc: string }; res: { ok: boolean } };
'library.list': { req: { workspaceId: string }; res: { autoDeployLibs: boolean; libs: { hash: string; cellBoc: string }[] } };
'library.add': { req: { workspaceId: string; cellBoc: string }; res: { hash: string; cellBoc: string } };
Expand Down
83 changes: 78 additions & 5 deletions packages/bridge/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import {
type Message,
type ShardAccount
} from '@ton/core';
import {
configParse18,
configParseGasLimitsPrices,
configParseMsgPrices,
parseValidatorSet
} from '@ton/ton';
import {
createShardAccount,
mergeCoverages,
Expand Down Expand Up @@ -173,6 +179,61 @@ async function runSend(ws: Workspace, msg: any) {
return ws.blockchain.sendMessage(built.msg, { randomSeed } as any);
}

type DecodedConfigField = { label: string; value: string };

function decodeConfigParam(id: number, cell: Cell): DecodedConfigField[] | null {
const s = cell.beginParse();
switch (id) {
case 18: {
const prices = configParse18(s);
const latest = prices[prices.length - 1];
if (!latest) return null;
return [
{ label: 'utime since', value: String(latest.utime_since) },
{ label: 'bit price ps', value: latest.bit_price_ps.toString() },
{ label: 'cell price ps', value: latest.cell_price_ps.toString() },
{ label: 'mc bit price ps', value: latest.mc_bit_price_ps.toString() },
{ label: 'mc cell price ps', value: latest.mc_cell_price_ps.toString() }
];
}
case 20:
case 21: {
const g = configParseGasLimitsPrices(s);
return [
{ label: 'gas price', value: g.other.gasPrice.toString() },
{ label: 'gas limit', value: g.other.gasLimit.toString() },
{ label: 'flat gas limit', value: g.flatLimit.toString() },
{ label: 'flat gas price', value: g.flatGasPrice.toString() },
{ label: 'block gas limit', value: g.other.blockGasLimit.toString() }
];
}
case 24:
case 25: {
const m = configParseMsgPrices(s);
return [
{ label: 'lump price', value: m.lumpPrice.toString() },
{ label: 'bit price', value: m.bitPrice.toString() },
{ label: 'cell price', value: m.cellPrice.toString() },
{ label: 'first frac', value: String(m.firstFrac) },
{ label: 'next frac', value: String(m.nextFrac) }
];
}
case 34: {
const v = parseValidatorSet(s);
if (!v) return null;
return [
{ label: 'utime since', value: String(v.timeSince) },
{ label: 'utime until', value: String(v.timeUntil) },
{ label: 'total', value: String(v.total) },
{ label: 'main', value: String(v.main) },
{ label: 'validators', value: String(v.list.size) }
];
}
default:
return null;
}
}

export const HANDLERS: Record<string, Handler> = {
// ── workspace ──
'workspace.open': async (p) => {
Expand Down Expand Up @@ -462,11 +523,23 @@ export const HANDLERS: Record<string, Handler> = {
);
for (const id of dict.keys().sort((a, b) => a - b)) {
const cell = dict.get(id)!;
params.push(
labels[id]
? { id, label: labels[id], kind: 'labeled', value: big(0n) }
: { id, kind: 'raw', value: { boc: cellToWire(cell) } }
);
if (!labels[id]) {
params.push({ id, kind: 'raw', value: { boc: cellToWire(cell) } });
continue;
}
let fields: DecodedConfigField[] | null = null;
try {
fields = decodeConfigParam(id, cell);
} catch {
/* unexpected TL-B tag — fall back to the raw cell below */
}
params.push({
id,
label: labels[id],
kind: 'labeled',
value: { boc: cellToWire(cell) },
...(fields ? { fields } : {})
});
}
} catch {
params.push({ id: 0, kind: 'raw', value: { boc: cellToWire(ws.blockchain.config) } });
Expand Down
25 changes: 24 additions & 1 deletion packages/mock-bridge/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,30 @@ wss.on('connection', (ws) => {
break;
}
case 'fork.status': ok({ enabled: true, mode: 'pinned-readonly', network: 'testnet', blockSeqno: 123456, accounts: [{ address: '0:pool', loaded: 'lazy', overridden: false }] }); break;
case 'config.get': ok({ params: [{ id: 18, label: 'storage prices', kind: 'labeled', value: '1' }, { id: 20, label: 'gas prices masterchain', kind: 'labeled', value: '1' }, { id: 99, kind: 'raw', value: { boc: 'te6ccgEBAQEAAgAAAA==' } }] }); break;
case 'config.get': ok({ params: [
{ id: 18, label: 'storage prices', kind: 'labeled', value: { boc: 'te6ccgEBAQEAAgAAAA==' }, fields: [
{ label: 'utime since', value: '0' },
{ label: 'bit price ps', value: '1' },
{ label: 'cell price ps', value: '500' },
{ label: 'mc bit price ps', value: '1000' },
{ label: 'mc cell price ps', value: '500000' }
] },
{ id: 20, label: 'gas prices (masterchain)', kind: 'labeled', value: { boc: 'te6ccgEBAQEAAgAAAA==' }, fields: [
{ label: 'gas price', value: '655360000' },
{ label: 'gas limit', value: '1000000' },
{ label: 'flat gas limit', value: '100' },
{ label: 'flat gas price', value: '1000000' },
{ label: 'block gas limit', value: '10000000' }
] },
{ id: 24, label: 'msg fwd prices (masterchain)', kind: 'labeled', value: { boc: 'te6ccgEBAQEAAgAAAA==' }, fields: [
{ label: 'lump price', value: '10000000' },
{ label: 'bit price', value: '655360000' },
{ label: 'cell price', value: '65536000000' },
{ label: 'first frac', value: '21845' },
{ label: 'next frac', value: '21845' }
] },
{ id: 99, kind: 'raw', value: { boc: 'te6ccgEBAQEAAgAAAA==' } }
] }); break;
case 'library.list': ok({ autoDeployLibs: true, libs: [{ hash: 'lib-hash', cellBoc: 'te6ccgEBAQEAAgAAAA==' }] }); break;
case 'library.add': ok({ hash: 'lib-new', cellBoc: req.params.cellBoc }); break;
case 'logs.subscribe': {
Expand Down