Skip to content

Commit bb2f4c3

Browse files
authored
hlp/sdk-finalize-and-quote-asset-update (#1874)
Signed-off-by: shankar <shankar@layerzerolabs.org>
1 parent aa1d2a6 commit bb2f4c3

22 files changed

Lines changed: 706 additions & 35 deletions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@layerzerolabs/hyperliquid-composer": patch
3+
"@layerzerolabs/oft-hyperliquid-example": patch
4+
---
5+
6+
sdk updates for quote asset improvement

examples/oft-hyperliquid/HYPERLIQUID.README.md

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,16 @@ npx @layerzerolabs/hyperliquid-composer trading-fee \
123123

124124
### 7. Enable Quote Token Capability (Optional)
125125

126-
Enables your token to be used as a quote asset for trading pairs. **Dependency:** Requires specific trading fee share value (see Step 6 above). See: [Permissionless Spot Quote Assets](https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/permissionless-spot-quote-assets)
126+
Enables your token to be used as a quote asset for trading pairs.
127+
128+
> ⚠️ **Important**: Review the complete [Quote Assets (Fee Tokens)](https://github.com/LayerZero-Labs/devtools/tree/main/packages/hyperliquid-composer/HYPERLIQUID.README.md#quote-assets-fee-tokens) section in the main documentation for:
129+
>
130+
> - Mainnet requirements (technical and liquidity)
131+
> - Testnet requirements (50 HYPE stake + active order book)
132+
> - Order book maintenance for `HYPE/YOUR_ASSET` pair
133+
> - Composer selection guidance (use `FeeToken` variant for quote assets)
134+
135+
**Dependency:** Requires trading fee share configuration (see Step 6 above).
127136

128137
```bash
129138
npx @layerzerolabs/hyperliquid-composer enable-quote-token \
@@ -161,6 +170,8 @@ npx @layerzerolabs/hyperliquid-composer request-evm-contract \
161170

162171
### 2. Finalize EVM Contract Link
163172

173+
#### Hypercore action method
174+
164175
```bash
165176
npx @layerzerolabs/hyperliquid-composer finalize-evm-contract \
166177
--token-index <coreIndex> \
@@ -169,6 +180,20 @@ npx @layerzerolabs/hyperliquid-composer finalize-evm-contract \
169180
[--log-level {info | verbose}]
170181
```
171182

183+
#### CoreWriter Method
184+
185+
Alternative method using direct CoreWriter interaction. This is useful if you prefer to use Foundry's `cast` command.
186+
187+
```bash
188+
npx @layerzerolabs/hyperliquid-composer finalize-evm-contract-corewriter \
189+
--token-index <coreIndex> \
190+
--nonce <nonce> \
191+
--network {testnet | mainnet} \
192+
[--log-level {info | verbose}]
193+
```
194+
195+
The command will output the calldata and a ready-to-use `cast send` command for finalizing the EVM contract link via the CoreWriter precompile at `0x3333333333333333333333333333333333333333`.
196+
172197
## Post-Launch Management
173198

174199
### Freeze/Unfreeze Users
@@ -264,6 +289,25 @@ npx @layerzerolabs/hyperliquid-composer spot-auction-status \
264289
[--log-level {info | verbose}]
265290
```
266291

292+
### Check if Token is Quote Asset
293+
294+
Check if a specific token is a quote asset, or list all quote assets when no token index is provided. Quote assets are automatically paired with HYPE when promoted by the Hyperliquid protocol.
295+
296+
```bash
297+
# List all quote assets
298+
npx @layerzerolabs/hyperliquid-composer list-quote-asset \
299+
--network {testnet | mainnet} \
300+
[--log-level {info | verbose}]
301+
302+
# Check if specific token is a quote asset
303+
npx @layerzerolabs/hyperliquid-composer list-quote-asset \
304+
--filter-token-index <coreIndex> \
305+
--network {testnet | mainnet} \
306+
[--log-level {info | verbose}]
307+
```
308+
309+
The command returns `yes` or `no` when checking a specific token, or lists all quote assets when no token index is provided.
310+
267311
## Utilities
268312

269313
### Convert Token Index to Bridge Address
@@ -490,11 +534,11 @@ npx @layerzerolabs/hyperliquid-composer trading-fee \
490534

491535
This step enables the token to be used as a quote asset for trading pairs. This allows other tokens to form trading pairs against your token (e.g., TOKEN/YOUR_TOKEN instead of only YOUR_TOKEN/USDC).
492536

493-
> ⚠️ **Requirements**:
537+
> ⚠️ **Important**: Review the complete [Quote Assets (Fee Tokens)](../../packages/hyperliquid-composer/HYPERLIQUID.README.md#quote-assets-fee-tokens) section in the main documentation for detailed requirements, including:
494538
>
495-
> - Requires specific trading fee share value (see Step 6/7 above)
496-
> - Review all requirements at: [Permissionless Spot Quote Assets](https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/permissionless-spot-quote-assets)
497-
> - Contact the Hyperliquid team for the most up-to-date information
539+
> - Mainnet: Complete technical and liquidity requirements
540+
> - Testnet: Simplified requirements (50 HYPE stake + active order book)
541+
> - Order book maintenance for `HYPE/YOUR_ASSET` pair after enablement
498542
>
499543
> 📝 **Note**: This can be executed after the trading fee share is set and even after deployment and linking are complete.
500544
@@ -506,6 +550,18 @@ npx @layerzerolabs/hyperliquid-composer enable-quote-token \
506550
[--log-level {info | verbose}]
507551
```
508552

553+
**Prerequisites:**
554+
555+
- Trading fee share must be set (see Step 6/7 above)
556+
- **Testnet**: 50 HYPE staked + active BUY and SELL limit orders on your token's order book
557+
- **Mainnet**: All requirements per [Hyperliquid's documentation](https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/permissionless-spot-quote-assets)
558+
559+
**After Execution:**
560+
561+
- A `HYPE/YOUR_ASSET` trading pair is automatically created
562+
- You must maintain order book requirements for the new `HYPE/ASSET` pair
563+
- Verify quote asset status with the `list-quote-asset` command
564+
509565
### Step 6.7/7 `enableAlignedQuoteToken` (Optional)
510566

511567
This step enables the token to be used as an aligned quote asset for trading pairs. Aligned quote tokens have special properties and requirements different from regular quote tokens.
@@ -559,6 +615,19 @@ npx @layerzerolabs/hyperliquid-composer finalize-evm-contract \
559615
--private-key $PRIVATE_KEY_HYPERLIQUID
560616
```
561617

618+
**Alternative: Using CoreWriter directly with Foundry**
619+
620+
If you prefer to use Foundry's `cast` command, you can generate the calldata and send the transaction directly:
621+
622+
```bash
623+
npx @layerzerolabs/hyperliquid-composer finalize-evm-contract-corewriter \
624+
--token-index <coreIndex> \
625+
--nonce <deployment-nonce> \
626+
--network {testnet | mainnet}
627+
```
628+
629+
This will output the calldata and a ready-to-use `cast send` command that you can execute directly.
630+
562631
## Deploy the Composer
563632

564633
While the composer could have been deployed at any point in time due to its statelessness, it is technically the final step of the deployment process. The following script automatically handles the block switching for you.

examples/oft-hyperliquid/deploy/MyHyperLiquidComposer_FeeAbstraction.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CHAIN_IDS,
88
EthersSigner,
99
getCoreSpotDeployment,
10+
isQuoteAsset,
1011
useBigBlock,
1112
useSmallBlock,
1213
} from '@layerzerolabs/hyperliquid-composer'
@@ -73,6 +74,30 @@ const deploy: DeployFunction = async (hre) => {
7374
// Validates and returns the native spot
7475
const hip1Token = getCoreSpotDeployment(coreSpotIndex, isTestnet)
7576

77+
// Check if the token is a quote asset - warn if it is
78+
console.log(`\nChecking if token ${coreSpotIndex} is a quote asset...`)
79+
const { isQuoteAsset: isQuote, tokenName } = await isQuoteAsset(isTestnet, parseInt(coreSpotIndex), loglevel)
80+
81+
if (isQuote) {
82+
console.warn(`\n[WARNING] Token ${coreSpotIndex}${tokenName ? ` (${tokenName})` : ''} IS a quote asset!`)
83+
console.warn(`For quote assets, you should use MyHyperLiquidComposer_FeeToken instead.`)
84+
console.warn(`FeeToken composer provides automatic user activation using the token itself.\n`)
85+
86+
const { continueAnyway } = await inquirer.prompt([
87+
{
88+
type: 'confirm',
89+
name: 'continueAnyway',
90+
message: 'Do you want to continue with FeeAbstraction anyway?',
91+
default: false,
92+
},
93+
])
94+
95+
if (!continueAnyway) {
96+
console.log('Deployment cancelled.')
97+
process.exit(0)
98+
}
99+
}
100+
76101
const { address: address_oft } = await hre.deployments.get(contractName_oft).catch(async () => {
77102
console.log(`Deployment file for ${contractName_oft}.json in deployments/${networkName} not found`)
78103
const { proceedWithOFTAddress } = await inquirer.prompt([

examples/oft-hyperliquid/deploy/MyHyperLiquidComposer_FeeToken.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CHAIN_IDS,
88
EthersSigner,
99
getCoreSpotDeployment,
10+
isQuoteAsset,
1011
useBigBlock,
1112
useSmallBlock,
1213
} from '@layerzerolabs/hyperliquid-composer'
@@ -52,6 +53,23 @@ const deploy: DeployFunction = async (hre) => {
5253
// Validates and returns the native spot
5354
const hip1Token = getCoreSpotDeployment(coreSpotIndex, isTestnet)
5455

56+
// Check if the token is a quote asset - required for FeeToken composer
57+
console.log(`\nChecking if token ${coreSpotIndex} is a quote asset...`)
58+
const { isQuoteAsset: isQuote, tokenName } = await isQuoteAsset(isTestnet, parseInt(coreSpotIndex), loglevel)
59+
60+
if (!isQuote) {
61+
console.error(`\n[ERROR] Token ${coreSpotIndex} is NOT a quote asset!`)
62+
console.error(`The FeeToken composer can ONLY be used with quote assets (tokens paired with HYPE).`)
63+
console.error(`\nThis token is not a quote asset. Please use one of the following composers instead:`)
64+
console.error(` - MyHyperliquidComposer (regular)`)
65+
console.error(` - MyHyperLiquidComposer_FeeAbstraction`)
66+
console.error(` - MyHyperLiquidComposer_Recoverable`)
67+
throw new Error(`Token ${coreSpotIndex} is not a quote asset. FeeToken composer requires a quote asset.`)
68+
}
69+
70+
console.log(`[OK] Confirmed: Token ${coreSpotIndex}${tokenName ? ` (${tokenName})` : ''} is a quote asset`)
71+
console.log(` FeeToken composer can be used for automatic user activation.\n`)
72+
5573
const { address: address_oft } = await hre.deployments.get(contractName_oft).catch(async () => {
5674
console.log(`Deployment file for ${contractName_oft}.json in deployments/${networkName} not found`)
5775
const { proceedWithOFTAddress } = await inquirer.prompt([

examples/oft-hyperliquid/deploy/MyHyperLiquidComposer_Recoverable.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CHAIN_IDS,
88
EthersSigner,
99
getCoreSpotDeployment,
10+
isQuoteAsset,
1011
useBigBlock,
1112
useSmallBlock,
1213
} from '@layerzerolabs/hyperliquid-composer'
@@ -54,6 +55,30 @@ const deploy: DeployFunction = async (hre) => {
5455
// Validates and returns the native spot
5556
const hip1Token = getCoreSpotDeployment(coreSpotIndex, isTestnet)
5657

58+
// Check if the token is a quote asset - warn if it is
59+
console.log(`\nChecking if token ${coreSpotIndex} is a quote asset...`)
60+
const { isQuoteAsset: isQuote, tokenName } = await isQuoteAsset(isTestnet, parseInt(coreSpotIndex), loglevel)
61+
62+
if (isQuote) {
63+
console.warn(`\n[WARNING] Token ${coreSpotIndex}${tokenName ? ` (${tokenName})` : ''} IS a quote asset!`)
64+
console.warn(`For quote assets, you should use MyHyperLiquidComposer_FeeToken instead.`)
65+
console.warn(`FeeToken composer provides automatic user activation using the token itself.\n`)
66+
67+
const { continueAnyway } = await inquirer.prompt([
68+
{
69+
type: 'confirm',
70+
name: 'continueAnyway',
71+
message: 'Do you want to continue with recoverable composer anyway?',
72+
default: false,
73+
},
74+
])
75+
76+
if (!continueAnyway) {
77+
console.log('Deployment cancelled.')
78+
process.exit(0)
79+
}
80+
}
81+
5782
const { address: address_oft } = await hre.deployments.get(contractName_oft).catch(async () => {
5883
console.log(`Deployment file for ${contractName_oft}.json in deployments/${networkName} not found`)
5984
const { proceedWithOFTAddress } = await inquirer.prompt([

examples/oft-hyperliquid/deploy/MyHyperliquidComposer.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CHAIN_IDS,
88
EthersSigner,
99
getCoreSpotDeployment,
10+
isQuoteAsset,
1011
useBigBlock,
1112
useSmallBlock,
1213
} from '@layerzerolabs/hyperliquid-composer'
@@ -52,6 +53,30 @@ const deploy: DeployFunction = async (hre) => {
5253
// Validates and returns the native spot
5354
const hip1Token = getCoreSpotDeployment(coreSpotIndex, isTestnet)
5455

56+
// Check if the token is a quote asset - warn if it is
57+
console.log(`\nChecking if token ${coreSpotIndex} is a quote asset...`)
58+
const { isQuoteAsset: isQuote, tokenName } = await isQuoteAsset(isTestnet, parseInt(coreSpotIndex), loglevel)
59+
60+
if (isQuote) {
61+
console.warn(`\n[WARNING] Token ${coreSpotIndex}${tokenName ? ` (${tokenName})` : ''} IS a quote asset!`)
62+
console.warn(`For quote assets, you should use MyHyperLiquidComposer_FeeToken instead.`)
63+
console.warn(`FeeToken composer provides automatic user activation using the token itself.\n`)
64+
65+
const { continueAnyway } = await inquirer.prompt([
66+
{
67+
type: 'confirm',
68+
name: 'continueAnyway',
69+
message: 'Do you want to continue with regular composer anyway?',
70+
default: false,
71+
},
72+
])
73+
74+
if (!continueAnyway) {
75+
console.log('Deployment cancelled.')
76+
process.exit(0)
77+
}
78+
}
79+
5580
const { address: address_oft } = await hre.deployments.get(contractName_oft).catch(async () => {
5681
console.log(`Deployment file for ${contractName_oft}.json in deployments/${networkName} not found`)
5782
const { proceedWithOFTAddress } = await inquirer.prompt([

0 commit comments

Comments
 (0)