Skip to content

Commit 7fff3be

Browse files
Revert "feat:Add pre-commit check (#684)"
This reverts commit 9f5c241.
1 parent 9f5c241 commit 7fff3be

32 files changed

Lines changed: 12486 additions & 10918 deletions

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @LeoHChen @DonFungible @jacob-tucker @allenchuang @limengformal @lucas2brh @yingyangxu2026 @bonnie57
1+
* @LeoHChen @DonFungible @jacob-tucker @allenchuang @limengformal @lucas2brh @yingyangxu2026 @chao-peng-story @roycezhaoca

.github/workflows/pr-internal.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,24 @@ on:
44
pull_request:
55
branches:
66
- main
7+
paths-ignore:
8+
- '.github/**'
9+
- '.github/CODEOWNERS'
10+
- '**/*.md'
11+
- 'docs/**'
12+
- '.gitignore'
13+
- 'LICENSE'
14+
715
push:
816
branches:
917
- main
18+
paths-ignore:
19+
- '.github/**'
20+
- '.github/CODEOWNERS'
21+
- '**/*.md'
22+
- 'docs/**'
23+
- '.gitignore'
24+
- 'LICENSE'
1025

1126
jobs:
1227
Timestamp:
@@ -19,6 +34,4 @@ jobs:
1934
with:
2035
sha: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
2136
ENVIRONMENT: "odyssey"
22-
secrets:
23-
WALLET_PRIVATE_KEY: ${{ secrets.WALLET_PRIVATE_KEY }}
24-
TEST_WALLET_ADDRESS: ${{ secrets.TEST_WALLET_ADDRESS }}
37+
secrets: inherit

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
node_modules
66
.pnp
77
.pnp.js
8-
.pnpm-store
98

109
# testing
1110
coverage

.husky/pre-commit

Lines changed: 0 additions & 1 deletion
This file was deleted.

.pre-commit-config.yaml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,3 @@ repos:
44
hooks:
55
- id: gitleaks
66
args: ['--verbose', '--redact']
7-
- repo: local
8-
hooks:
9-
- id: lint-staged
10-
name: lint-staged (ESLint)
11-
entry: pnpm run lint-staged
12-
language: system
13-
pass_filenames: false

CONTRIBUTING.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ This section provides the instructions on how to build Story Protocol SDK from s
2121
- Install PNPM: Execute `npm install -g pnpm`
2222
- Install TypeScript: Run `pnpm add typescript -D`
2323
- Install Yalc: Use `npm install -g yalc`
24-
- Install dependencies: `pnpm install` (this automatically sets up Husky git hooks for ESLint checks on commit)
2524

2625
#### Steps for Using Yalc for Local Testing of Core-SDK
2726

docs/v1.4.4-release.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# v1.4.4 Release Notes
2+
3+
## New Features
4+
5+
### Account Abstraction (AA) Wallet Support — `txHashResolver`
6+
7+
Added support for Account Abstraction wallets (e.g. **ZeroDev**, **Dynamic Global Wallet**) via a new optional `txHashResolver` configuration parameter.
8+
9+
#### Problem
10+
11+
When using AA wallets, `writeContract` returns a **UserOperation hash** instead of a standard **transaction hash**. The SDK's `waitForTransactionReceipt` only works with regular transaction hashes, causing AA wallet transactions to fail silently or hang.
12+
13+
#### Solution
14+
15+
A new `txHashResolver` option can be passed when creating a `StoryClient`. This function resolves UserOperation hashes into on-chain transaction hashes before the SDK waits for receipts. The resolver is applied transparently — **all existing SDK methods work without any changes**.
16+
17+
#### Usage
18+
19+
**Normal wallets** — no changes needed:
20+
21+
```typescript
22+
const client = StoryClient.newClient({
23+
transport: http("https://aeneid.storyrpc.io"),
24+
account: privateKeyToAccount("0x..."),
25+
});
26+
```
27+
28+
**ZeroDev AA wallet — Using Kernel Client directly (recommended)**:
29+
30+
ZeroDev's `createKernelAccountClient` returns a viem smart account client whose `writeContract` internally sends the UserOperation, waits for the bundler to include it on-chain, and returns the **real tx hash**. Therefore **`txHashResolver` is NOT needed** — simply pass the kernel client as the wallet:
31+
32+
```typescript
33+
import { createKernelAccountClient } from "@zerodev/sdk";
34+
35+
const kernelClient = await createKernelAccountClient({ /* ... */ });
36+
37+
const client = StoryClient.newClientUseWallet({
38+
transport: http("https://aeneid.storyrpc.io"),
39+
wallet: kernelClient,
40+
// No txHashResolver needed — kernel client handles it internally
41+
});
42+
43+
// All SDK methods work as usual
44+
const result = await client.ipAsset.mintAndRegisterIpAssetWithPilTerms({
45+
spgNftContract: "0x...",
46+
terms: [],
47+
});
48+
```
49+
50+
**Raw UserOp wallet + txHashResolver (for AA wallets that return userOpHash)**:
51+
52+
Some AA wallet integrations return the **UserOperation hash** directly from `writeContract` without internally waiting for the bundler receipt. For these wallets, configure `txHashResolver` to convert the userOpHash into the real on-chain tx hash:
53+
54+
```typescript
55+
const client = StoryClient.newClientUseWallet({
56+
transport: http("https://aeneid.storyrpc.io"),
57+
wallet: rawAAWallet, // writeContract returns userOpHash
58+
txHashResolver: async (userOpHash) => {
59+
const receipt = await bundlerClient.waitForUserOperationReceipt({
60+
hash: userOpHash,
61+
});
62+
return receipt.receipt.transactionHash;
63+
},
64+
});
65+
```
66+
67+
> **How to tell?** If the hash returned by the AA wallet's `writeContract` cannot be found as a transaction on a block explorer, it is a userOpHash and you need `txHashResolver`. If it can be found on-chain directly, the wallet already handles resolution internally and no resolver is needed.
68+
69+
**Dynamic Global Wallet**:
70+
71+
```typescript
72+
const client = StoryClient.newClientUseWallet({
73+
transport: http("https://aeneid.storyrpc.io"),
74+
wallet: dynamicWalletClient,
75+
txHashResolver: async (userOpHash) => {
76+
// Use Dynamic's bundler client to resolve the hash
77+
const receipt = await dynamicBundlerClient.waitForUserOperationReceipt({
78+
hash: userOpHash,
79+
});
80+
return receipt.receipt.transactionHash;
81+
},
82+
});
83+
```
84+
85+
#### Supported Factory Methods
86+
87+
`txHashResolver` is supported by all three client creation methods:
88+
89+
- `StoryClient.newClient({ ..., txHashResolver })`
90+
- `StoryClient.newClientUseWallet({ ..., txHashResolver })`
91+
- `StoryClient.newClientUseAccount({ ..., txHashResolver })`
92+
93+
#### API Reference
94+
95+
```typescript
96+
/**
97+
* A function that resolves a hash returned by writeContract into an actual
98+
* transaction hash that can be used with waitForTransactionReceipt.
99+
*
100+
* @param hash - The hash returned by writeContract (could be a userOpHash or txHash)
101+
* @returns The resolved on-chain transaction hash
102+
*/
103+
type TxHashResolver = (hash: Hash) => Promise<Hash>;
104+
```
105+
106+
## Changed Files
107+
108+
| File | Change |
109+
|------|--------|
110+
| `packages/core-sdk/src/types/config.ts` | Added `TxHashResolver` type; added `txHashResolver` to `StoryConfig`, `UseWalletStoryConfig`, `UseAccountStoryConfig` |
111+
| `packages/core-sdk/src/client.ts` | Added `applyTxHashResolver()` method; patched `rpcClient.waitForTransactionReceipt` when resolver is provided; forwarded resolver in factory methods |
112+
| `packages/core-sdk/test/unit/client.test.ts` | Added unit tests that verify resolver wiring, hash transformation, and constructor-time patching |
113+
| `packages/core-sdk/test/integration/txHashResolver.test.ts` | ZeroDev E2E integration tests (6 passing), covering both AA wallet modes |
114+
| `packages/core-sdk/package.json` | Added `@zerodev/sdk`, `@zerodev/ecdsa-validator` as devDependencies |
115+
| `packages/core-sdk/src/utils/oov3.ts` | Added retry logic (up to 5 attempts) to `settleAssertion()` for `Assertion not expired` errors |
116+
| `packages/core-sdk/test/unit/utils/oov3.test.ts` | Added `chai-as-promised`; added unit tests for retry success and max-retries failure |
117+
| `packages/core-sdk/test/integration/dispute.test.ts` | Increased assertion expiry wait from 3s to 15s |
118+
| `packages/core-sdk/test/integration/group.test.ts` | Added `this.retries(2)` to flaky royalty/reward tests |
119+
| `packages/core-sdk/test/integration/ipAsset.test.ts` | Added `this.retries(2)` to batch register test |
120+
| `.github/workflows/pr-internal.yml` | Changed to `secrets: inherit` to forward all repository secrets |
121+
122+
## CI / Test Stability Improvements
123+
124+
This release also includes fixes for 5 flaky integration tests that were failing due to testnet timing and nonce contention issues. These failures were **pre-existing** and unrelated to the `txHashResolver` feature.
125+
126+
### Fix #1 — Dispute: `Assertion not expired`
127+
128+
**Root cause**: `settleAssertion` was called before the on-chain assertion liveness period had actually expired. The previous 3-second wait was insufficient given variable testnet block times.
129+
130+
**Fix**:
131+
- `src/utils/oov3.ts``settleAssertion()` now retries up to 5 times (with 3s delay) when encountering `Assertion not expired`, instead of failing immediately.
132+
- `test/integration/dispute.test.ts` — Increased the post-dispute wait from **3s → 15s** in both `beforeEach` and the multicall tagging test.
133+
- `test/unit/utils/oov3.test.ts` — Added unit tests for retry success and max-retries failure; fixed `chai-as-promised` import.
134+
135+
### Fix #2#4 — Group: `receiver IP not registered` + cascading failures
136+
137+
**Root cause**: Nonce contention from a shared test wallet caused intermittent transaction failures. When `payRoyaltyOnBehalf` failed in the "collect royalties" test, the subsequent "get claimable reward" and "claim reward" tests also failed because they depended on the state from the first test.
138+
139+
**Fix**:
140+
- `test/integration/group.test.ts` — Added `this.retries(2)` to all three tests (`collect royalties`, `get claimable reward`, `claim reward`). Mocha will automatically retry each test up to 2 additional times on failure.
141+
142+
### Fix #5 — IP Asset: `replacement transaction underpriced`
143+
144+
**Root cause**: Nonce collision — a pending transaction from a previous test occupied the same nonce with equal or higher gas, causing the RPC node to reject the replacement.
145+
146+
**Fix**:
147+
- `test/integration/ipAsset.test.ts` — Added `this.retries(2)` to the `should successfully register IP assets with multicall disabled` test.
148+
149+
### CI Workflow: `secrets: inherit`
150+
151+
- `.github/workflows/pr-internal.yml` — Changed from explicitly listing individual secrets to `secrets: inherit`, so all repository secrets (including `BUNDLER_RPC_URL`) are automatically forwarded to the reusable workflow.
152+
153+
## Test Coverage Notes
154+
155+
- **Unit tests**: Validate that `txHashResolver` is invoked before receipt polling and that the resolved hash is used for receipt lookup.
156+
- **Integration tests — Pass-through & Simulated**: Cover normal wallet pass-through and simulated AA hash mapping behavior.
157+
- **Integration tests — ZeroDev E2E (2 scenarios)**:
158+
- **Kernel client as wallet**: Verifies that `writeContract` returns a real txHash and the SDK works correctly without a resolver.
159+
- **Raw userOp wallet + txHashResolver**: Uses a custom wallet wrapper (whose `writeContract` returns a userOpHash) to verify end-to-end that the resolver converts the userOpHash into a real on-chain txHash.
160+
- ZeroDev E2E tests require `BUNDLER_RPC_URL` and `WALLET_PRIVATE_KEY` in `.env`. Tests are automatically skipped when these are not configured.

package.json

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,14 @@
88
"scripts": {
99
"build": "turbo run build",
1010
"lint": "turbo run lint",
11-
"lint-staged": "node scripts/precommit-run-eslint.mjs",
1211
"fix": "turbo run fix",
1312
"test": "turbo run test --no-cache --concurrency=1",
14-
"test:integration": "turbo run test:integration --no-cache",
15-
"prepare": "husky"
13+
"test:integration": "turbo run test:integration --no-cache"
1614
},
1715
"devDependencies": {
1816
"@changesets/cli": "2.29.6",
19-
"eslint": "^9.26.0",
20-
"husky": "^9.1.7",
21-
"lint-staged": "^15.2.1",
2217
"turbo": "^1.10.13"
2318
},
24-
"lint-staged": {
25-
"packages/core-sdk/**/*.{ts,tsx,js,jsx,mjs,cjs}": "node scripts/precommit-eslint-core-sdk.mjs"
26-
},
2719
"engines": {
2820
"node": "^20.0.0"
2921
},

packages/core-sdk/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
"@types/mocha": "^10.0.2",
5151
"@types/node": "^20.8.2",
5252
"@types/sinon": "^10.0.18",
53+
"@zerodev/ecdsa-validator": "^5.4.9",
54+
"@zerodev/sdk": "^5.5.7",
5355
"c8": "^8.0.1",
5456
"chai": "^4.3.10",
5557
"chai-as-promised": "^7.1.1",

0 commit comments

Comments
 (0)