Skip to content
Closed
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
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"index_name": "morph_doc",
"start_urls": ["https://docs.morph.network/"],
"start_urls": ["https://docs.morph.network"],
"sitemap_urls": [
"https://docs.morph.network/sitemap.xml"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ lang: en-US
description: Official JavaScript/TypeScript SDK for interacting with the Morph Network.
---

import AltFeeQuickStartDemo from "@site/src/components/AltFee/AltFeeQuickStartDemo";
import QuerySupportedTokensDemo from "@site/src/components/AltFee/QuerySupportedTokensDemo";
import ChainConfigDemo from "@site/src/components/AltFee/ChainConfigDemo";

# Morph SDK

> Official JavaScript/TypeScript SDK for interacting with the Morph Network
Expand Down Expand Up @@ -150,7 +154,8 @@ import { privateKeyToAccount } from "viem/accounts";
import { morphHoodiTestnet } from "@morph-network/viem";

// 1. Create account
const account = privateKeyToAccount("0x...");
const privateKey = "<YOUR_PRIVATE_KEY>";
const account = privateKeyToAccount(privateKey);

// 2. Public Client (read)
const publicClient = createPublicClient({
Expand All @@ -174,13 +179,13 @@ async function sendAltFeeTransaction() {
const hash = await walletClient.sendTransaction({
account,
to: "0x...",
value: parseEther("0.01"),
value: parseEther("0.001"),
nonce,
gas: 100000n,
maxFeePerGas: 15000000n,
maxPriorityFeePerGas: 14000000n,
// Alt Fee fields
feeTokenID: 6, // Token Registry ID
feeTokenID: 4, // Token Registry ID for USDT
feeLimit: 252637086960555000n, // Max token payment
Comment on lines +188 to 189

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent feeTokenID values in documentation.

The examples now consistently use feeTokenID: 4 (USDT), but there are inconsistencies in the output comments that were not updated:

  • Line 290: // => [{ tokenID: 6, tokenAddress: "0x..." }, ...]
  • Lines 505-506: console.log(tx.feeTokenID); // 6

Consider updating these output comments to maintain consistency, or clarify that tokenID: 6 represents a different token in the registry output.

🤖 Prompt for AI Agents
In `@docs/build-on-morph/sdk/js-sdk.mdx` around lines 188 - 189, Update the
inconsistent token ID comments to match the example's feeTokenID of 4: change
the sample output comment that shows "tokenID: 6" to "tokenID: 4" (or explicitly
state that tokenID 6 refers to a different registry token), and change the
console output comment for tx.feeTokenID to reflect 4 instead of 6; search for
occurrences of feeTokenID, tokenID and tx.feeTokenID in this document and ensure
output comments and explanatory text consistently reference the same registry ID
or call out when a different token is being demonstrated.

});

Expand All @@ -190,6 +195,9 @@ async function sendAltFeeTransaction() {
sendAltFeeTransaction();
```

<AltFeeQuickStartDemo />


### Ethers v6 quick start

Send an Alt Fee Transaction with the Ethers v6 adapter:
Expand All @@ -209,13 +217,13 @@ async function main() {
// 3. Send Alt Fee Transaction
const tx = await signer.sendTransaction({
to: "0x...",
value: parseEther("0.01"),
value: parseEther("0.001"),
chainId: MORPH_HOODI_TESTNET.chainId,
gasLimit: 100000n,
maxFeePerGas: 15000000n,
maxPriorityFeePerGas: 14000000n,
// Alt Fee fields
feeTokenID: 6,
feeTokenID: 4,
feeLimit: 252637086960555000n,
});

Expand All @@ -226,12 +234,13 @@ async function main() {
### Ethers v5 quick start

```typescript
import { ethers, providers } from "ethers";
import { providers, utils } from "ethers";
import { MorphSigner, MORPH_HOODI_TESTNET } from "@morph-network/ethers5";

async function main() {
// 1. Provider
const provider = new providers.Web3Provider(window.ethereum);
await provider.send("eth_requestAccounts", []);

// 2. Wrap signer
const web3Signer = provider.getSigner();
Expand All @@ -240,17 +249,17 @@ async function main() {
// 3. Send Alt Fee Transaction
const tx = await signer.sendTransaction({
to: "0x...",
value: ethers.utils.parseEther("0.01"),
value: utils.parseEther("0.001"),
chainId: MORPH_HOODI_TESTNET.chainId,
gasLimit: ethers.BigNumber.from(100000),
maxFeePerGas: ethers.BigNumber.from(15000000),
maxPriorityFeePerGas: ethers.BigNumber.from(14000000),
gasLimit: utils.hexlify(100000),
maxFeePerGas: utils.parseUnits("0.015", "gwei"),
maxPriorityFeePerGas: utils.parseUnits("0.014", "gwei"),
// Alt Fee fields
feeTokenID: 6,
feeLimit: ethers.BigNumber.from("252637086960555000"),
feeTokenID: 4,
feeLimit: utils.parseUnits("1", 6), // 1 USDT/USDC
});

console.log("Transaction response:", tx);
console.log("Transaction hash:", tx.hash);
}
```

Expand Down Expand Up @@ -295,6 +304,8 @@ async function getTokenInfo(tokenId: number) {
}
```

<QuerySupportedTokensDemo />

---

## API Reference
Expand Down Expand Up @@ -342,7 +353,7 @@ import { morphHoodiTestnet } from "@morph-network/viem";
morphHoodiTestnet.id // 2910
morphHoodiTestnet.name // "Morph Hoodi Testnet"
morphHoodiTestnet.nativeCurrency // { name: "Ethereum", symbol: "ETH", decimals: 18 }
morphHoodiTestnet.rpcUrls.default.http // ["https://rpc-hoodi.morphl2.io"]
morphHoodiTestnet.rpcUrls.default.http // ["https://rpc-hoodi.morph.network"]
```

**Usage:**
Expand All @@ -359,6 +370,8 @@ const client = createWalletClient({
});
```

<ChainConfigDemo />

---

#### Serialization helpers
Expand Down Expand Up @@ -389,7 +402,7 @@ const serialized = serializeTransaction({
maxFeePerGas: 15000000n,
maxPriorityFeePerGas: 14000000n,
nonce: 0,
feeTokenID: 6,
feeTokenID: 4,
feeLimit: 252637086960555000n,
});

Expand All @@ -416,13 +429,13 @@ import { serializeAltFeeTransaction } from "@morph-network/viem";

const serialized = serializeAltFeeTransaction({
chainId: 2910,
to: "0x92be4a7c135314932b481c4c5a9e391644b91fe5",
to: "0x...",
value: 10000000000000000n,
gas: 1000000n,
maxFeePerGas: 15316544n,
maxPriorityFeePerGas: 14116544n,
nonce: 5,
feeTokenID: 6,
feeTokenID: 4,
feeLimit: 252637086960555000n,
accessList: [],
});
Expand Down Expand Up @@ -465,7 +478,7 @@ console.log(tx);
// chainId: 2910,
// to: "0x...",
// value: 10000000000000000n,
// feeTokenID: 6,
// feeTokenID: 4,
// feeLimit: 252637086960555000n,
// ...
// }
Expand Down Expand Up @@ -535,7 +548,7 @@ console.log("Recovered from:", recoveredFrom);

#### Utility

##### `numeric(value)`
##### `numericCore(value)`

Convert between number, bigint, and hex.

Expand All @@ -559,24 +572,24 @@ Convert between number, bigint, and hex.
**Example:**

```typescript
import { numeric } from "@morph-network/viem";
import { numericCore } from "@morph-network/viem";

// Convert types
numeric(0).hex(); // "0x"
numeric(1).hex(); // "0x1"
numeric(255).hex(); // "0xff"
numeric(256n).hex(); // "0x100"
numeric("0x10").hex(); // "0x10"
numericCore(0).hex(); // "0x"
numericCore(1).hex(); // "0x1"
numericCore(255).hex(); // "0xff"
numericCore(256n).hex(); // "0x100"
numericCore("0x10").hex(); // "0x10"

// Other conversions
numeric("0xff").number(); // 255
numeric(100).bigint(); // 100n
numeric(1000).uint16(); // "0x03e8"
numericCore("0xff").number(); // 255
numericCore(100).bigint(); // 100n
numericCore(1000).uint16(); // "0x03e8"

// In a transaction
const tx = {
feeTokenID: numeric(6).hex(),
feeLimit: numeric(252637086960555000n).hex(),
feeTokenID: numericCore(6).hex(),
feeLimit: numericCore(252637086960555000n).hex(),
};
```

Expand All @@ -602,7 +615,7 @@ const tx: AltFeeTransaction = {
data: "0x",
accessList: [],
// Alt Fee fields
feeTokenID: 6,
feeTokenID: 4,
feeLimit: 252637086960555000n,
};
```
Expand Down Expand Up @@ -651,7 +664,7 @@ Factory to wrap an Ethers Signer with Morph Alt Fee support.
**Example:**

```typescript
import { BrowserProvider } from "ethers";
import { BrowserProvider, parseEther } from "ethers";
import { MorphSigner } from "@morph-network/ethers";

const provider = new BrowserProvider(window.ethereum);
Expand All @@ -663,8 +676,8 @@ const signer = MorphSigner.from(browserSigner);
// Alt Fee tx supported now
await signer.sendTransaction({
to: "0x...",
value: parseEther("0.01"),
feeTokenID: 6,
value: parseEther("0.001"),
feeTokenID: 4,
feeLimit: 252637086960555000n,
});
```
Expand Down Expand Up @@ -694,13 +707,15 @@ Sign standard or Alt Fee transactions.
| `maxPriorityFeePerGas` | `bigint` | Yes | Max priority fee |
| `nonce` | `number` | No | Tx nonce |
| `feeTokenID` | `number` | No* | Token ID (required for Alt Fee) |
| `feeLimit` | `bigint` | No* | Token fee cap (required for Alt Fee) |
| `feeLimit` | `bigint \| Hex` | No* | Token fee cap (required for Alt Fee). Accepts bigint or hex string. |

**Example:**

```typescript
import { parseEther } from "ethers";

const signedTx = await signer.signTransaction({
to: "0x78fE92CBB534C4d35A8cB0F3F2C58a5AA7DF2DA6",
to: "0x...",
chainId: 2910,
value: parseEther("0.001"),
gasLimit: 1000000n,
Expand All @@ -724,8 +739,10 @@ Send standard or Alt Fee transactions.
**Example:**

```typescript
import { parseEther } from "ethers";

const txResponse = await signer.sendTransaction({
to: "0x78fE92CBB534C4d35A8cB0F3F2C58a5AA7DF2DA6",
to: "0x...",
chainId: 2910,
value: parseEther("0.001"),
gasLimit: 1000000n,
Expand Down Expand Up @@ -753,8 +770,10 @@ Estimate gas, including Alt Fee support.
**Example:**

```typescript
import { parseEther } from "ethers";

const gasEstimate = await signer.estimateGas({
to: "0x78fE92CBB534C4d35A8cB0F3F2C58a5AA7DF2DA6",
to: "0x...",
chainId: 2910,
value: parseEther("0.001"),
gasLimit: 1000000n,
Expand All @@ -778,10 +797,13 @@ Populate missing fields (nonce/gasLimit/etc.).
**Example:**

```typescript
import { parseEther } from "ethers";

const populatedTx = await signer.populateTransaction({
to: "0x78fE92CBB534C4d35A8cB0F3F2C58a5AA7DF2DA6",
to: "0x...",
value: parseEther("0.001"),
feeTokenID: 3,
feeLimit: 1000000n, // Required for Alt Fee transactions
});

console.log("Populated tx:", populatedTx);
Expand All @@ -808,39 +830,44 @@ const signer = MorphSigner.from(web3Signer);
```

```typescript
import { ethers } from "ethers";
import { utils } from "ethers";

const signedTx = await signer.signTransaction({
to: "0x...",
chainId: 2910,
value: ethers.utils.parseEther("0.001"),
gasLimit: ethers.BigNumber.from(1000000),
maxFeePerGas: ethers.BigNumber.from(15316544),
maxPriorityFeePerGas: ethers.BigNumber.from(14116544),
value: utils.parseEther("0.001"),
gasLimit: utils.hexlify(1000000),
maxFeePerGas: utils.hexlify(15316544),
maxPriorityFeePerGas: utils.hexlify(14116544),
feeTokenID: 2,
feeLimit: ethers.BigNumber.from("252637086960555000"),
feeLimit: "0x0381653dfd7f0f8", // hex string or bigint
});
```

```typescript
import { utils } from "ethers";

const txResponse = await signer.sendTransaction({
to: "0x...",
chainId: 2910,
value: ethers.utils.parseEther("0.001"),
gasLimit: ethers.BigNumber.from(1000000),
maxFeePerGas: ethers.BigNumber.from(15316544),
maxPriorityFeePerGas: ethers.BigNumber.from(14116544),
value: utils.parseEther("0.001"),
gasLimit: utils.hexlify(1000000),
maxFeePerGas: utils.hexlify(15316544),
maxPriorityFeePerGas: utils.hexlify(14116544),
feeTokenID: 3,
feeLimit: utils.parseUnits("1", 6), // Required! 1 USDT/USDC
});
```

```typescript
import { utils } from "ethers";

const gasEstimate = await signer.estimateGas({
to: "0x...",
chainId: 2910,
value: ethers.utils.parseEther("0.001"),
value: utils.parseEther("0.001"),
feeTokenID: 3,
feeLimit: ethers.BigNumber.from("252637086960555000"),
feeLimit: utils.parseUnits("1", 6),
});

console.log("Estimated gas:", gasEstimate.toString());
Expand All @@ -855,8 +882,10 @@ Chain definitions as a standalone package, so you can reuse Morph networks acros
**Example:**

```typescript
import { morphMainnet, morphHoodiTestnet } from "@morph-network/chain";
import { MORPH_MAINNET, MORPH_HOODI_TESTNET } from "@morph-network/chain";

console.log(morphMainnet.id); // 2818
console.log(morphHoodiTestnet.rpcUrls.default.http[0]); // https://rpc-hoodi.morphl2.io
console.log(MORPH_MAINNET.chainId); // 2818
console.log(MORPH_HOODI_TESTNET.rpcUrl); // https://rpc-hoodi.morphl2.io
```
Comment on lines +885 to 889

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent RPC URL in documentation.

Line 888 shows the old RPC URL https://rpc-hoodi.morphl2.io, but line 356 documents the updated URL as https://rpc-hoodi.morph.network. The comment should be updated for consistency.

📝 Suggested fix
-console.log(MORPH_HOODI_TESTNET.rpcUrl); // https://rpc-hoodi.morphl2.io
+console.log(MORPH_HOODI_TESTNET.rpcUrl); // https://rpc-hoodi.morph.network
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { MORPH_MAINNET, MORPH_HOODI_TESTNET } from "@morph-network/chain";
console.log(morphMainnet.id); // 2818
console.log(morphHoodiTestnet.rpcUrls.default.http[0]); // https://rpc-hoodi.morphl2.io
console.log(MORPH_MAINNET.chainId); // 2818
console.log(MORPH_HOODI_TESTNET.rpcUrl); // https://rpc-hoodi.morphl2.io
```
import { MORPH_MAINNET, MORPH_HOODI_TESTNET } from "@morph-network/chain";
console.log(MORPH_MAINNET.chainId); // 2818
console.log(MORPH_HOODI_TESTNET.rpcUrl); // https://rpc-hoodi.morph.network
🤖 Prompt for AI Agents
In `@docs/build-on-morph/sdk/js-sdk.mdx` around lines 885 - 889, The documentation
example uses an outdated RPC URL in the console output comment; update the
comment that logs MORPH_HOODI_TESTNET.rpcUrl to the current URL
(`https://rpc-hoodi.morph.network`) so it matches the rest of the docs and the
value provided by the MORPH_HOODI_TESTNET.rpcUrl constant; locate the example
using the symbols MORPH_MAINNET, MORPH_HOODI_TESTNET and the rpcUrl property and
replace the old URL text in the comment accordingly.


> **Note:** The viem-style chain objects (`morphMainnet`, `morphHoodiTestnet`) are only exported from `@morph-network/viem`, not from `@morph-network/chain`.
Loading