Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f39c6a9
feat(kernel-utils): add sheaf programming module
grypez Mar 9, 2026
9b9c809
test(kernel-utils): update index exports snapshot for sheaf and GET_D…
grypez Mar 9, 2026
cd38818
refactor(kernel-utils): require guard in getSection, add getGlobalSec…
grypez Mar 9, 2026
9e21a83
test(kernel-utils): use vi.fn() spies in sheafify e2e tests to verify…
grypez Mar 9, 2026
03e3ac6
fix(kernel-utils): fix false negative in collectSheafGuard for rest-a…
grypez Mar 9, 2026
64fb99e
feat(kernel-utils): metadata as polynomials of invocation data
grypez Mar 10, 2026
449819d
fix(kernel-utils): fix build errors in sheafify metadata eval
grypez Mar 10, 2026
fe344b1
feat(kernel-utils): treat {} as empty sheaf metadata
grypez Apr 1, 2026
e758e76
refactor(kernel-utils): redesign Lift as AsyncGenerator coroutine
grypez Apr 13, 2026
e2d2783
test(kernel-utils): add unit tests for lift composition helpers
grypez Apr 13, 2026
1f2963e
fix(kernel-utils): driveLift throws with accumulated errors as cause
grypez Apr 13, 2026
7929912
docs(kernel-utils): document sheaf module in README
grypez Apr 13, 2026
eccd3eb
feat(kernel-utils): add makeRemoteSection for CapTP remote refs as sh…
grypez Apr 20, 2026
2fcd8f4
feat(kernel-utils): add getDiscoverableSection, deprecate global sect…
grypez Apr 20, 2026
2c25f2f
fix(kernel-utils): allow passable default guards for async section in…
grypez Apr 24, 2026
17ea8ec
fix(kernel-utils): bind method calls in makeRemoteSection via E proxy
grypez Apr 24, 2026
cadfa28
fix(kernel-utils): suppress noUncheckedIndexedAccess false positive i…
grypez Apr 24, 2026
03e8ace
docs: Update changelogs
grypez Apr 24, 2026
3f23786
docs(kernel-utils): Improve sheaf documentation
grypez Apr 27, 2026
996610a
refactor(kernel-utils): remove unused sheaf revocation API
grypez Apr 27, 2026
3fa355f
docs(kernel-utils): fix sheaf doc errors from revocation removal
grypez Apr 27, 2026
73ae266
refactor(kernel-utils): extract buildMethodGuard to eliminate duplica…
grypez Apr 27, 2026
bb3618c
fix(kernel-utils): harden sheafify return value and frozenSections
grypez Apr 27, 2026
5abc6e7
feat(kernel-utils): export noopLift as canonical single-section place…
grypez Apr 27, 2026
62f6970
feat(kernel-utils): add makeSection to eliminate as-unknown-as-Sectio…
grypez Apr 27, 2026
fc2304c
refactor(kernel-utils): centralize guard payload helpers and move asy…
grypez Apr 27, 2026
8a2c424
fix(kernel-utils): improve error message for lift object-identity pro…
grypez Apr 27, 2026
881b5cc
docs(kernel-utils): note that source metadata is for trust-boundary u…
grypez Apr 27, 2026
2329cdf
refactor(kernel-utils): remove getStalk and guardCoversPoint from pub…
grypez Apr 27, 2026
0798843
refactor(kernel-utils): inline driveLift into sheafify and remove dri…
grypez Apr 27, 2026
7a0a2f7
refactor(kernel-utils): rename MetaDataSpec → MetadataSpec
grypez Apr 27, 2026
af73489
refactor(kernel-utils): remove Presheaf<M> thin alias
grypez Apr 27, 2026
573126b
docs(kernel-utils): document why Sheaf.getSection returns object
grypez Apr 27, 2026
88d0e31
refactor(kernel-utils): remove dead resolvedGuard alias in sheafify
grypez Apr 27, 2026
d4ab36e
test(kernel-utils): add getSection explicit-guard test coverage
grypez Apr 27, 2026
c6ed13e
test(kernel-utils): add e2e test for multi-candidate lift retry on ha…
grypez Apr 27, 2026
04e180f
refactor(kernel-utils): unexport collectSheafGuard from public index
grypez Apr 27, 2026
4f47c89
docs(kernel-utils): documentation pass for sheaf module
grypez Apr 27, 2026
7f0d41a
test(kernel-utils): add failing tests for driveLift snapshot and meta…
grypez Apr 27, 2026
88bc8a3
fix(kernel-utils): pass error snapshots to lift generator in driveLift
grypez Apr 27, 2026
8b0520f
fix(kernel-utils): use type-tagged encoding in metadataKey to prevent…
grypez Apr 27, 2026
d3b397d
refactor(kernel-utils): move sheaf exports to ./sheaf subpath
grypez Apr 27, 2026
cf3ff6d
test(kernel-utils): add failing test for NaN constraint detection in …
grypez Apr 27, 2026
2d84d4a
fix(kernel-utils): use Object.is for value equality in decomposeMetadata
grypez Apr 27, 2026
b5efb50
test(kernel-utils): add failing test for -0 vs +0 collapse in metadat…
grypez Apr 27, 2026
c43872e
fix(kernel-utils): handle -0 in encodeMetadataEntry
grypez Apr 27, 2026
c293202
feat(evm-wallet): use sheaves for capability routing in away-coordinator
grypez Apr 19, 2026
9a16612
fix(evm-wallet): lowercase token address in transferFungible dispatch
grypez Apr 24, 2026
883ba77
test(evm-wallet): update delegation twin e2e for sheaf fall-through s…
grypez Apr 24, 2026
45cdd4d
fix(evm-wallet): update sheaf imports to @metamask/kernel-utils/sheaf…
grypez Apr 27, 2026
637f95e
fix(evm-wallet): update token normalization test to inspect guard ins…
grypez Apr 27, 2026
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
23 changes: 20 additions & 3 deletions packages/evm-wallet-experiment/src/lib/delegation-twin.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
matches,
getInterfaceGuardPayload,
getMethodGuardPayload,
} from '@endo/patterns';
import type { InterfaceGuard, MethodGuard, Pattern } from '@endo/patterns';
import { describe, expect, it, vi } from 'vitest';

import type {
Expand Down Expand Up @@ -122,11 +128,11 @@ describe('makeDelegationTwin', () => {
});

describe('transferFungible twin', () => {
it('normalizes checksummed token address to lowercase in section.token', () => {
it('normalizes checksummed token address to lowercase in transferFungible guard', () => {
const CHECKSUMMED_TOKEN =
'0xAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAa' as Address;
const redeemFn = vi.fn().mockResolvedValue(TX_HASH);
const section = makeDelegationTwin({
makeDelegationTwin({
grant: {
method: 'transferFungible',
token: CHECKSUMMED_TOKEN,
Expand All @@ -135,7 +141,18 @@ describe('makeDelegationTwin', () => {
},
redeemFn,
});
expect(section.token).toBe(CHECKSUMMED_TOKEN.toLowerCase());
// The guard's first arg for transferFungible is M.eq(token.toLowerCase()).
// If the token is not normalized here, incoming calls with the canonical
// lowercase address would be rejected by the guard at dispatch time.
const ifacePayload = getInterfaceGuardPayload(
lastInterfaceGuard as InterfaceGuard,
) as unknown as { methodGuards: Record<string, MethodGuard> };
const methodPayload = getMethodGuardPayload(
ifacePayload.methodGuards.transferFungible,
) as unknown as { argGuards: Pattern[] };
const tokenGuard = methodPayload.argGuards[0];
expect(matches(CHECKSUMMED_TOKEN.toLowerCase(), tokenGuard)).toBe(true);
expect(matches(CHECKSUMMED_TOKEN, tokenGuard)).toBe(false);
});

it('exposes transferFungible method', () => {
Expand Down
22 changes: 14 additions & 8 deletions packages/evm-wallet-experiment/src/lib/delegation-twin.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import { M } from '@endo/patterns';
import { makeDiscoverableExo } from '@metamask/kernel-utils/discoverable';
import { constant } from '@metamask/kernel-utils/sheaf';
import type { PresheafSection } from '@metamask/kernel-utils/sheaf';

import { encodeTransfer } from './erc20.ts';
import { METHOD_CATALOG } from './method-catalog.ts';
import type { Address, DelegationGrant, Execution, Hex } from '../types.ts';

export type DelegationSection =
| { exo: object; method: 'transferNative' }
| { exo: object; method: 'transferFungible'; token: Address };
type AwayMetadata = { mode: string; delegationId?: string };

type DelegationTwinOptions = {
grant: DelegationGrant;
redeemFn: (execution: Execution) => Promise<Hex>;
};

/**
* Build a DelegationSection for a delegation grant.
* Build a PresheafSection for a delegation grant.
* The resulting exo exposes the method covered by the grant, enforcing
* local guards and (for transferFungible) a local budget tracker.
*
* @param options - Twin construction options.
* @param options.grant - The semantic delegation grant to wrap.
* @param options.redeemFn - Submits an Execution to the delegation framework.
* @returns A DelegationSection wrapping the delegation exo.
* @returns A PresheafSection with constant delegation metadata.
*/
export function makeDelegationTwin(
options: DelegationTwinOptions,
): DelegationSection {
): PresheafSection<AwayMetadata> {
const { grant, redeemFn } = options;
const { delegation } = grant;
const idPrefix = delegation.id.slice(0, 12);
Expand Down Expand Up @@ -90,7 +90,10 @@ export function makeDelegationTwin(
interfaceGuard,
);

return { exo, method: 'transferNative' };
return {
exo,
metadata: constant({ mode: 'delegation', delegationId: delegation.id }),
};
}

// transferFungible — normalize token address to lowercase for consistent matching.
Expand Down Expand Up @@ -152,5 +155,8 @@ export function makeDelegationTwin(
interfaceGuard,
);

return { exo, method: 'transferFungible', token };
return {
exo,
metadata: constant({ mode: 'delegation', delegationId: delegation.id }),
};
}
Loading
Loading