@walletconnect/staking-cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -11,6 +11,7 @@ var STAKING_REWARD_DISTRIBUTOR_ADDRESS = "0xF368F535e329c6d08DFf0d4b2dA961C4e7F3
11
11
  var OPTIMISM_RPC_URL = "https://mainnet.optimism.io";
12
12
  var FOUNDATION_API_URL = "https://api.walletconnect.network";
13
13
  var ONE_WEEK_IN_SECONDS = 604800;
14
+ var MIN_REMAINING_LOCK_SECONDS = ONE_WEEK_IN_SECONDS;
14
15
  var WCT_DECIMALS = 18;
15
16
  var APY_SLOPE = -0.06464;
16
17
  var APY_INTERCEPT = 12.0808;
@@ -308,6 +309,17 @@ Adding ${amount} WCT${extendingTime ? `, extending lock to ${formatDate(Number(e
308
309
  console.log("\nUpdating lock (amount + time)...");
309
310
  txHash = await sendTx(wallet, address, buildUpdateLock(amountWei, effectiveUnlockTime));
310
311
  } else {
312
+ const now = BigInt(Math.floor(Date.now() / 1e3));
313
+ const remaining = lock.end - now;
314
+ if (remaining < BigInt(MIN_REMAINING_LOCK_SECONDS)) {
315
+ const days = Number(remaining) / 86400;
316
+ console.error(
317
+ `
318
+ Cannot add to position: lock expires in ~${Math.ceil(days)} day(s), which is below the minimum remaining period of 1 week.
319
+ Re-run with a longer --weeks value to extend your lock.`
320
+ );
321
+ return;
322
+ }
311
323
  console.log("\nIncreasing lock amount...");
312
324
  txHash = await sendTx(wallet, address, buildIncreaseLockAmount(amountWei));
313
325
  }
package/dist/index.cjs CHANGED
@@ -1,22 +1,24 @@
1
- "use strict";var y=Object.defineProperty;var it=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var ct=(t,n)=>{for(var o in n)y(t,o,{get:n[o],enumerable:!0})},lt=(t,n,o,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of rt(n))!st.call(t,e)&&e!==o&&y(t,e,{get:()=>n[e],enumerable:!(i=it(n,e))||i.enumerable});return t};var ut=t=>lt(y({},"__esModule",{value:!0}),t);var ft={};ct(ft,{CAIP2_CHAIN_ID:()=>D,CHAIN_ID:()=>M,CLI_METADATA:()=>H,L2_WCT_ADDRESS:()=>g,STAKE_WEIGHT_ADDRESS:()=>c,STAKING_REWARD_DISTRIBUTOR_ADDRESS:()=>b,balance:()=>at,buildAllowanceCallData:()=>E,buildApprove:()=>S,buildBalanceOfCallData:()=>P,buildClaim:()=>W,buildCreateLock:()=>C,buildIncreaseLockAmount:()=>_,buildIncreaseUnlockTime:()=>G,buildLocksCallData:()=>R,buildUpdateLock:()=>I,buildWithdrawAll:()=>h,calculateAPY:()=>N,calculateWeeklyAPY:()=>$,claim:()=>ot,fetchStakeWeight:()=>L,fetchStaking:()=>d,formatDate:()=>u,formatWCT:()=>k,stake:()=>tt,status:()=>et,unstake:()=>nt});module.exports=ut(ft);var Z=require("viem");var M=10,D="eip155:10",g="0xeF4461891DfB3AC8572cCf7C794664A8DD927945",c="0x521B4C065Bbdbe3E20B3727340730936912DfA46",b="0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF",p="https://mainnet.optimism.io",K="https://api.walletconnect.network";var H={name:"walletconnect-staking",description:"WalletConnect WCT Staking CLI",url:"https://walletconnect.com",icons:[]};var s=require("viem");var U=(0,s.parseAbi)(["function approve(address spender, uint256 value) returns (bool)","function balanceOf(address account) view returns (uint256)","function allowance(address owner, address spender) view returns (uint256)"]),m=(0,s.parseAbi)(["function createLock(uint256 amount, uint256 unlockTime)","function updateLock(uint256 amount, uint256 unlockTime)","function increaseLockAmount(uint256 amount)","function increaseUnlockTime(uint256 newUnlockTime)","function withdrawAll()","function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)"]),gt=(0,s.parseAbi)(["function claim(address user) returns (uint256)"]);function S(t,n){return{to:g,data:(0,s.encodeFunctionData)({abi:U,functionName:"approve",args:[t,n]})}}function C(t,n){return{to:c,data:(0,s.encodeFunctionData)({abi:m,functionName:"createLock",args:[t,n]})}}function I(t,n){return{to:c,data:(0,s.encodeFunctionData)({abi:m,functionName:"updateLock",args:[t,n]})}}function _(t){return{to:c,data:(0,s.encodeFunctionData)({abi:m,functionName:"increaseLockAmount",args:[t]})}}function G(t){return{to:c,data:(0,s.encodeFunctionData)({abi:m,functionName:"increaseUnlockTime",args:[t]})}}function h(){return{to:c,data:(0,s.encodeFunctionData)({abi:m,functionName:"withdrawAll"})}}function W(t){return{to:b,data:(0,s.encodeFunctionData)({abi:gt,functionName:"claim",args:[t]})}}function P(t){return{to:g,data:(0,s.encodeFunctionData)({abi:U,functionName:"balanceOf",args:[t]})}}function E(t,n){return{to:g,data:(0,s.encodeFunctionData)({abi:U,functionName:"allowance",args:[t,n]})}}function R(t){return{to:c,data:(0,s.encodeFunctionData)({abi:m,functionName:"locks",args:[t]})}}var O=require("viem");var mt=1;async function v(t,n,o){let i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:mt++,method:t,params:n})});if(!i.ok)throw new Error(`RPC request failed: ${i.status} ${i.statusText}`);let e=await i.json();if(e.error)throw new Error(`RPC error: ${e.error.message}`);return e.result}async function j(t,n){return v("eth_call",[{to:t.to,data:t.data},"latest"],n)}async function F(t,n=p){let o=await j(t,n),[i]=(0,O.decodeAbiParameters)([{type:"uint256"}],o);return i}async function q(t,n,o=p){let i=await v("eth_estimateGas",[{from:t,to:n.to,data:n.data,value:"0x0"},"latest"],o),e=BigInt(i);return`0x${(e+e/5n).toString(16)}`}async function V(t,n=p,{intervalMs:o=2e3,timeoutMs:i=6e4}={}){let e=Date.now();for(;Date.now()-e<i;){try{let a=await v("eth_getTransactionReceipt",[t],n);if(a){if(a.status==="0x0")throw new Error(`Transaction ${t} reverted`);return}}catch(a){if(a instanceof Error&&a.message.includes("reverted"))throw a}await new Promise(a=>setTimeout(a,o))}throw new Error(`Transaction ${t} not confirmed within ${i/1e3}s`)}async function X(t,n=p){let o=await j(t,n),[i,e,a]=(0,O.decodeAbiParameters)([{type:"int128"},{type:"uint256"},{type:"uint256"}],o);return{amount:BigInt(i),end:e,transferredAmount:a}}function J(){return process.env.FOUNDATION_API_URL||K}async function d(t){let n=`${J()}/staking?address=${t}`,o=await fetch(n);if(!o.ok)throw new Error(`Foundation API error: ${o.status} ${o.statusText}`);return await o.json()}async function L(){let t=`${J()}/stake-weight`,n=await fetch(t);if(!n.ok)throw new Error(`Foundation API error: ${n.status} ${n.statusText}`);return await n.json()}var Q=require("viem");function k(t){let n=(0,Q.formatUnits)(t,18);return parseFloat(n).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}function u(t){return new Date(t*1e3).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function N(t){return Math.max(t/1e6*-.06464+12.0808,0)}function $(t,n){return t*(Math.min(n,104)/52)}function r(t,n){return` ${t.padEnd(12)} ${n}`}function dt(t){let n=Math.floor(Date.now()/1e3);return BigInt(Math.floor((n+t*604800)/604800))*BigInt(604800)}async function f(t,n,o){let i=await q(n,o);return t.request({chainId:D,request:{method:"eth_sendTransaction",params:[{from:n,to:o.to,data:o.data,value:"0x0",gas:i}]}})}async function tt(t,n,o,i){let e=(0,Z.parseUnits)(o,18),a=dt(i),l=await X(R(n)),T=l.amount>0n;T&&(console.log(`
2
- Existing staking position:`),console.log(r("Staked",`${k(BigInt(l.amount))} WCT`)),console.log(r("Unlocks",u(Number(l.end)))));let x=a,Y=!T||a>l.end;if(T&&a<=l.end&&(x=l.end,console.log(`
3
- Requested unlock (${u(Number(a))}) is before existing lock end.`),console.log(`Keeping current unlock date: ${u(Number(l.end))}`)),console.log(`
4
- Adding ${o} WCT${Y?`, extending lock to ${u(Number(x))}`:""}...`),await F(E(n,c))<e){console.log(`
5
- Approving WCT spend...`);let B=await f(t,n,S(c,e));console.log(r("Approve tx",B)),console.log("Waiting for confirmation..."),await V(B)}let w;T?Y?(console.log(`
6
- Updating lock (amount + time)...`),w=await f(t,n,I(e,x))):(console.log(`
7
- Increasing lock amount...`),w=await f(t,n,_(e))):(console.log(`
8
- Creating new lock...`),w=await f(t,n,C(e,x))),console.log(r("Tx hash",w)),console.log(`
9
- Stake submitted successfully.`)}async function nt(t,n){let o=await d(n);if(!o.position){console.log(`
1
+ "use strict";var U=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var lt=Object.prototype.hasOwnProperty;var ut=(t,n)=>{for(var o in n)U(t,o,{get:n[o],enumerable:!0})},gt=(t,n,o,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of ct(n))!lt.call(t,e)&&e!==o&&U(t,e,{get:()=>n[e],enumerable:!(i=st(n,e))||i.enumerable});return t};var mt=t=>gt(U({},"__esModule",{value:!0}),t);var xt={};ut(xt,{CAIP2_CHAIN_ID:()=>b,CHAIN_ID:()=>Y,CLI_METADATA:()=>H,L2_WCT_ADDRESS:()=>g,STAKE_WEIGHT_ADDRESS:()=>l,STAKING_REWARD_DISTRIBUTOR_ADDRESS:()=>S,balance:()=>it,buildAllowanceCallData:()=>R,buildApprove:()=>C,buildBalanceOfCallData:()=>P,buildClaim:()=>W,buildCreateLock:()=>I,buildIncreaseLockAmount:()=>h,buildIncreaseUnlockTime:()=>j,buildLocksCallData:()=>N,buildUpdateLock:()=>_,buildWithdrawAll:()=>E,calculateAPY:()=>$,calculateWeeklyAPY:()=>y,claim:()=>et,fetchStakeWeight:()=>L,fetchStaking:()=>d,formatDate:()=>u,formatWCT:()=>k,stake:()=>nt,status:()=>at,unstake:()=>ot});module.exports=mt(xt);var tt=require("viem");var Y=10,b="eip155:10",g="0xeF4461891DfB3AC8572cCf7C794664A8DD927945",l="0x521B4C065Bbdbe3E20B3727340730936912DfA46",S="0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF",f="https://mainnet.optimism.io",G="https://api.walletconnect.network";var H={name:"walletconnect-staking",description:"WalletConnect WCT Staking CLI",url:"https://walletconnect.com",icons:[]};var s=require("viem");var O=(0,s.parseAbi)(["function approve(address spender, uint256 value) returns (bool)","function balanceOf(address account) view returns (uint256)","function allowance(address owner, address spender) view returns (uint256)"]),m=(0,s.parseAbi)(["function createLock(uint256 amount, uint256 unlockTime)","function updateLock(uint256 amount, uint256 unlockTime)","function increaseLockAmount(uint256 amount)","function increaseUnlockTime(uint256 newUnlockTime)","function withdrawAll()","function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)"]),dt=(0,s.parseAbi)(["function claim(address user) returns (uint256)"]);function C(t,n){return{to:g,data:(0,s.encodeFunctionData)({abi:O,functionName:"approve",args:[t,n]})}}function I(t,n){return{to:l,data:(0,s.encodeFunctionData)({abi:m,functionName:"createLock",args:[t,n]})}}function _(t,n){return{to:l,data:(0,s.encodeFunctionData)({abi:m,functionName:"updateLock",args:[t,n]})}}function h(t){return{to:l,data:(0,s.encodeFunctionData)({abi:m,functionName:"increaseLockAmount",args:[t]})}}function j(t){return{to:l,data:(0,s.encodeFunctionData)({abi:m,functionName:"increaseUnlockTime",args:[t]})}}function E(){return{to:l,data:(0,s.encodeFunctionData)({abi:m,functionName:"withdrawAll"})}}function W(t){return{to:S,data:(0,s.encodeFunctionData)({abi:dt,functionName:"claim",args:[t]})}}function P(t){return{to:g,data:(0,s.encodeFunctionData)({abi:O,functionName:"balanceOf",args:[t]})}}function R(t,n){return{to:g,data:(0,s.encodeFunctionData)({abi:O,functionName:"allowance",args:[t,n]})}}function N(t){return{to:l,data:(0,s.encodeFunctionData)({abi:m,functionName:"locks",args:[t]})}}var v=require("viem");var pt=1;async function M(t,n,o){let i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:pt++,method:t,params:n})});if(!i.ok)throw new Error(`RPC request failed: ${i.status} ${i.statusText}`);let e=await i.json();if(e.error)throw new Error(`RPC error: ${e.error.message}`);return e.result}async function q(t,n){return M("eth_call",[{to:t.to,data:t.data},"latest"],n)}async function F(t,n=f){let o=await q(t,n),[i]=(0,v.decodeAbiParameters)([{type:"uint256"}],o);return i}async function V(t,n,o=f){let i=await M("eth_estimateGas",[{from:t,to:n.to,data:n.data,value:"0x0"},"latest"],o),e=BigInt(i);return`0x${(e+e/5n).toString(16)}`}async function X(t,n=f,{intervalMs:o=2e3,timeoutMs:i=6e4}={}){let e=Date.now();for(;Date.now()-e<i;){try{let a=await M("eth_getTransactionReceipt",[t],n);if(a){if(a.status==="0x0")throw new Error(`Transaction ${t} reverted`);return}}catch(a){if(a instanceof Error&&a.message.includes("reverted"))throw a}await new Promise(a=>setTimeout(a,o))}throw new Error(`Transaction ${t} not confirmed within ${i/1e3}s`)}async function J(t,n=f){let o=await q(t,n),[i,e,a]=(0,v.decodeAbiParameters)([{type:"int128"},{type:"uint256"},{type:"uint256"}],o);return{amount:BigInt(i),end:e,transferredAmount:a}}function z(){return process.env.FOUNDATION_API_URL||G}async function d(t){let n=`${z()}/staking?address=${t}`,o=await fetch(n);if(!o.ok)throw new Error(`Foundation API error: ${o.status} ${o.statusText}`);return await o.json()}async function L(){let t=`${z()}/stake-weight`,n=await fetch(t);if(!n.ok)throw new Error(`Foundation API error: ${n.status} ${n.statusText}`);return await n.json()}var Z=require("viem");function k(t){let n=(0,Z.formatUnits)(t,18);return parseFloat(n).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}function u(t){return new Date(t*1e3).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function $(t){return Math.max(t/1e6*-.06464+12.0808,0)}function y(t,n){return t*(Math.min(n,104)/52)}function r(t,n){return` ${t.padEnd(12)} ${n}`}function kt(t){let n=Math.floor(Date.now()/1e3);return BigInt(Math.floor((n+t*604800)/604800))*BigInt(604800)}async function p(t,n,o){let i=await V(n,o);return t.request({chainId:b,request:{method:"eth_sendTransaction",params:[{from:n,to:o.to,data:o.data,value:"0x0",gas:i}]}})}async function nt(t,n,o,i){let e=(0,tt.parseUnits)(o,18),a=kt(i),c=await J(N(n)),A=c.amount>0n;A&&(console.log(`
2
+ Existing staking position:`),console.log(r("Staked",`${k(BigInt(c.amount))} WCT`)),console.log(r("Unlocks",u(Number(c.end)))));let T=a,B=!A||a>c.end;if(A&&a<=c.end&&(T=c.end,console.log(`
3
+ Requested unlock (${u(Number(a))}) is before existing lock end.`),console.log(`Keeping current unlock date: ${u(Number(c.end))}`)),console.log(`
4
+ Adding ${o} WCT${B?`, extending lock to ${u(Number(T))}`:""}...`),await F(R(n,l))<e){console.log(`
5
+ Approving WCT spend...`);let D=await p(t,n,C(l,e));console.log(r("Approve tx",D)),console.log("Waiting for confirmation..."),await X(D)}let w;if(!A)console.log(`
6
+ Creating new lock...`),w=await p(t,n,I(e,T));else if(B)console.log(`
7
+ Updating lock (amount + time)...`),w=await p(t,n,_(e,T));else{let D=BigInt(Math.floor(Date.now()/1e3)),K=c.end-D;if(K<BigInt(604800)){let rt=Number(K)/86400;console.error(`
8
+ Cannot add to position: lock expires in ~${Math.ceil(rt)} day(s), which is below the minimum remaining period of 1 week.
9
+ Re-run with a longer --weeks value to extend your lock.`);return}console.log(`
10
+ Increasing lock amount...`),w=await p(t,n,h(e))}console.log(r("Tx hash",w)),console.log(`
11
+ Stake submitted successfully.`)}async function ot(t,n){let o=await d(n);if(!o.position){console.log(`
10
12
  No staking position found.`);return}if(o.position.unlocksAt){let e=new Date(o.position.unlocksAt).getTime()/1e3,a=Math.floor(Date.now()/1e3);if(e>a){console.log(`
11
13
  Lock has not expired yet. Unlocks ${u(e)}.`);return}}console.log(`
12
- Withdrawing all staked WCT...`);let i=await f(t,n,h());console.log(r("Tx hash",i)),console.log(`
13
- Unstake submitted successfully.`)}async function ot(t,n){let o=await d(n);if(!o.rewards||o.rewards.amount==="0"){console.log(`
14
+ Withdrawing all staked WCT...`);let i=await p(t,n,E());console.log(r("Tx hash",i)),console.log(`
15
+ Unstake submitted successfully.`)}async function et(t,n){let o=await d(n);if(!o.rewards||o.rewards.amount==="0"){console.log(`
14
16
  No rewards to claim.`);return}console.log(`
15
- Claiming ${o.rewards.amount} WCT in rewards...`);let i=await f(t,n,W(n));console.log(r("Tx hash",i)),console.log(`
16
- Claim submitted successfully.`)}async function et(t){let[n,o]=await Promise.all([d(t),L()]);if(console.log(`
17
+ Claiming ${o.rewards.amount} WCT in rewards...`);let i=await p(t,n,W(n));console.log(r("Tx hash",i)),console.log(`
18
+ Claim submitted successfully.`)}async function at(t){let[n,o]=await Promise.all([d(t),L()]);if(console.log(`
17
19
  Staking status for ${t}
18
20
  `),!n.position)console.log(` No staking position found.
19
- `);else{let a=n.position;if(console.log(r("Amount",`${a.amount} WCT`)),console.log(r("Permanent",a.isPermanent?"Yes":"No")),console.log(r("Created",new Date(a.createdAt).toLocaleDateString("en-US"))),a.unlocksAt&&console.log(r("Unlocks",new Date(a.unlocksAt).toLocaleDateString("en-US"))),a.duration){let l=Math.round(parseInt(a.duration,10)/604800);console.log(r("Duration",`${l} week(s)`))}console.log()}n.rewards&&console.log(r("Rewards",`${n.rewards.amount} WCT`));let i=parseFloat(o.stakeWeight),e=N(i);if(console.log(r("Base APY",`${e.toFixed(2)}%`)),n.position?.duration){let a=Math.round(parseInt(n.position.duration,10)/604800),l=$(e,a);console.log(r("Your APY",`${l.toFixed(2)}%`))}console.log()}async function at(t){let n=await F(P(t));console.log(`
21
+ `);else{let a=n.position;if(console.log(r("Amount",`${a.amount} WCT`)),console.log(r("Permanent",a.isPermanent?"Yes":"No")),console.log(r("Created",new Date(a.createdAt).toLocaleDateString("en-US"))),a.unlocksAt&&console.log(r("Unlocks",new Date(a.unlocksAt).toLocaleDateString("en-US"))),a.duration){let c=Math.round(parseInt(a.duration,10)/604800);console.log(r("Duration",`${c} week(s)`))}console.log()}n.rewards&&console.log(r("Rewards",`${n.rewards.amount} WCT`));let i=parseFloat(o.stakeWeight),e=$(i);if(console.log(r("Base APY",`${e.toFixed(2)}%`)),n.position?.duration){let a=Math.round(parseInt(n.position.duration,10)/604800),c=y(e,a);console.log(r("Your APY",`${c.toFixed(2)}%`))}console.log()}async function it(t){let n=await F(P(t));console.log(`
20
22
  ${r("WCT balance",`${k(n)} WCT`)}
21
23
  `)}0&&(module.exports={CAIP2_CHAIN_ID,CHAIN_ID,CLI_METADATA,L2_WCT_ADDRESS,STAKE_WEIGHT_ADDRESS,STAKING_REWARD_DISTRIBUTOR_ADDRESS,balance,buildAllowanceCallData,buildApprove,buildBalanceOfCallData,buildClaim,buildCreateLock,buildIncreaseLockAmount,buildIncreaseUnlockTime,buildLocksCallData,buildUpdateLock,buildWithdrawAll,calculateAPY,calculateWeeklyAPY,claim,fetchStakeWeight,fetchStaking,formatDate,formatWCT,stake,status,unstake});
22
24
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands.ts","../src/constants.ts","../src/contracts.ts","../src/rpc.ts","../src/api.ts","../src/format.ts"],"sourcesContent":["export { stake, unstake, claim, status, balance } from \"./commands.js\";\nexport { formatWCT, formatDate, calculateAPY, calculateWeeklyAPY } from \"./format.js\";\nexport { fetchStaking, fetchStakeWeight } from \"./api.js\";\nexport type { StakingPosition, StakingRewards, StakingResponse, StakeWeightResponse } from \"./api.js\";\nexport {\n buildApprove,\n buildCreateLock,\n buildUpdateLock,\n buildIncreaseLockAmount,\n buildIncreaseUnlockTime,\n buildWithdrawAll,\n buildClaim,\n buildBalanceOfCallData,\n buildAllowanceCallData,\n buildLocksCallData,\n} from \"./contracts.js\";\nexport type { TxData } from \"./contracts.js\";\nexport {\n CHAIN_ID,\n CAIP2_CHAIN_ID,\n L2_WCT_ADDRESS,\n STAKE_WEIGHT_ADDRESS,\n STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n CLI_METADATA,\n} from \"./constants.js\";\n","import { parseUnits } from \"viem\";\nimport type { WalletConnectCLI } from \"@walletconnect/cli-sdk\";\nimport {\n CAIP2_CHAIN_ID,\n STAKE_WEIGHT_ADDRESS,\n ONE_WEEK_IN_SECONDS,\n WCT_DECIMALS,\n} from \"./constants.js\";\nimport {\n buildApprove,\n buildCreateLock,\n buildUpdateLock,\n buildIncreaseLockAmount,\n buildWithdrawAll,\n buildClaim,\n buildBalanceOfCallData,\n buildAllowanceCallData,\n buildLocksCallData,\n type TxData,\n} from \"./contracts.js\";\nimport { readUint256, readLocks, estimateGas, waitForTx } from \"./rpc.js\";\nimport { fetchStaking, fetchStakeWeight } from \"./api.js\";\nimport { formatWCT, formatDate, calculateAPY, calculateWeeklyAPY, label } from \"./format.js\";\n\n// ---- Helpers ---------------------------------------------------------- //\n\nfunction computeUnlockTime(weeks: number): bigint {\n const now = Math.floor(Date.now() / 1000);\n return (BigInt(Math.floor((now + weeks * ONE_WEEK_IN_SECONDS) / ONE_WEEK_IN_SECONDS)) *\n BigInt(ONE_WEEK_IN_SECONDS));\n}\n\nasync function sendTx(\n wallet: WalletConnectCLI,\n from: string,\n tx: TxData,\n): Promise<string> {\n const gas = await estimateGas(from, tx);\n return wallet.request<string>({\n chainId: CAIP2_CHAIN_ID,\n request: {\n method: \"eth_sendTransaction\",\n params: [{ from, to: tx.to, data: tx.data, value: \"0x0\", gas }],\n },\n });\n}\n\n// ---- Commands --------------------------------------------------------- //\n\nexport async function stake(\n wallet: WalletConnectCLI,\n address: string,\n amount: string,\n weeks: number,\n): Promise<void> {\n const amountWei = parseUnits(amount, WCT_DECIMALS);\n const requestedUnlockTime = computeUnlockTime(weeks);\n\n // Read on-chain position to determine the right action\n const lock = await readLocks(buildLocksCallData(address));\n const hasPosition = lock.amount > 0n;\n\n if (hasPosition) {\n console.log(\"\\nExisting staking position:\");\n console.log(label(\"Staked\", `${formatWCT(BigInt(lock.amount))} WCT`));\n console.log(label(\"Unlocks\", formatDate(Number(lock.end))));\n }\n\n // Determine effective unlock time — never shorten an existing lock\n let effectiveUnlockTime = requestedUnlockTime;\n const extendingTime = !hasPosition || requestedUnlockTime > lock.end;\n\n if (hasPosition && requestedUnlockTime <= lock.end) {\n effectiveUnlockTime = lock.end;\n console.log(`\\nRequested unlock (${formatDate(Number(requestedUnlockTime))}) is before existing lock end.`);\n console.log(`Keeping current unlock date: ${formatDate(Number(lock.end))}`);\n }\n\n console.log(`\\nAdding ${amount} WCT${extendingTime ? `, extending lock to ${formatDate(Number(effectiveUnlockTime))}` : \"\"}...`);\n\n // Check allowance and approve if needed\n const allowance = await readUint256(buildAllowanceCallData(address, STAKE_WEIGHT_ADDRESS));\n if (allowance < amountWei) {\n console.log(\"\\nApproving WCT spend...\");\n const approveTxHash = await sendTx(wallet, address, buildApprove(STAKE_WEIGHT_ADDRESS, amountWei));\n console.log(label(\"Approve tx\", approveTxHash));\n console.log(\"Waiting for confirmation...\");\n await waitForTx(approveTxHash);\n }\n\n let txHash: string;\n\n if (!hasPosition) {\n console.log(\"\\nCreating new lock...\");\n txHash = await sendTx(wallet, address, buildCreateLock(amountWei, effectiveUnlockTime));\n } else if (extendingTime) {\n console.log(\"\\nUpdating lock (amount + time)...\");\n txHash = await sendTx(wallet, address, buildUpdateLock(amountWei, effectiveUnlockTime));\n } else {\n console.log(\"\\nIncreasing lock amount...\");\n txHash = await sendTx(wallet, address, buildIncreaseLockAmount(amountWei));\n }\n\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nStake submitted successfully.\");\n}\n\nexport async function unstake(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.position) {\n console.log(\"\\nNo staking position found.\");\n return;\n }\n\n if (staking.position.unlocksAt) {\n const unlocksAt = new Date(staking.position.unlocksAt).getTime() / 1000;\n const now = Math.floor(Date.now() / 1000);\n if (unlocksAt > now) {\n console.log(`\\nLock has not expired yet. Unlocks ${formatDate(unlocksAt)}.`);\n return;\n }\n }\n\n console.log(\"\\nWithdrawing all staked WCT...\");\n const txHash = await sendTx(wallet, address, buildWithdrawAll());\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nUnstake submitted successfully.\");\n}\n\nexport async function claim(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.rewards || staking.rewards.amount === \"0\") {\n console.log(\"\\nNo rewards to claim.\");\n return;\n }\n\n console.log(`\\nClaiming ${staking.rewards.amount} WCT in rewards...`);\n const txHash = await sendTx(wallet, address, buildClaim(address));\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nClaim submitted successfully.\");\n}\n\nexport async function status(address: string): Promise<void> {\n const [staking, stakeWeightRes] = await Promise.all([\n fetchStaking(address),\n fetchStakeWeight(),\n ]);\n\n console.log(`\\nStaking status for ${address}\\n`);\n\n if (!staking.position) {\n console.log(\" No staking position found.\\n\");\n } else {\n const pos = staking.position;\n console.log(label(\"Amount\", `${pos.amount} WCT`));\n console.log(label(\"Permanent\", pos.isPermanent ? \"Yes\" : \"No\"));\n console.log(label(\"Created\", new Date(pos.createdAt).toLocaleDateString(\"en-US\")));\n if (pos.unlocksAt) {\n console.log(label(\"Unlocks\", new Date(pos.unlocksAt).toLocaleDateString(\"en-US\")));\n }\n if (pos.duration) {\n const durationWeeks = Math.round(parseInt(pos.duration, 10) / ONE_WEEK_IN_SECONDS);\n console.log(label(\"Duration\", `${durationWeeks} week(s)`));\n }\n console.log();\n }\n\n if (staking.rewards) {\n console.log(label(\"Rewards\", `${staking.rewards.amount} WCT`));\n }\n\n const stakeWeight = parseFloat(stakeWeightRes.stakeWeight);\n const baseAPY = calculateAPY(stakeWeight);\n console.log(label(\"Base APY\", `${baseAPY.toFixed(2)}%`));\n\n if (staking.position?.duration) {\n const weeks = Math.round(parseInt(staking.position.duration, 10) / ONE_WEEK_IN_SECONDS);\n const weeklyAPY = calculateWeeklyAPY(baseAPY, weeks);\n console.log(label(\"Your APY\", `${weeklyAPY.toFixed(2)}%`));\n }\n\n console.log();\n}\n\nexport async function balance(address: string): Promise<void> {\n const bal = await readUint256(buildBalanceOfCallData(address));\n console.log(`\\n${label(\"WCT balance\", `${formatWCT(bal)} WCT`)}\\n`);\n}\n","/** Optimism chain ID */\nexport const CHAIN_ID = 10;\nexport const CAIP2_CHAIN_ID = \"eip155:10\";\n\n/** Contract addresses on Optimism */\nexport const L2_WCT_ADDRESS = \"0xeF4461891DfB3AC8572cCf7C794664A8DD927945\";\nexport const STAKE_WEIGHT_ADDRESS = \"0x521B4C065Bbdbe3E20B3727340730936912DfA46\";\nexport const STAKING_REWARD_DISTRIBUTOR_ADDRESS = \"0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF\";\n\n/** Public Optimism RPC endpoint */\nexport const OPTIMISM_RPC_URL = \"https://mainnet.optimism.io\";\n\n/** Foundation API */\nexport const FOUNDATION_API_URL = \"https://api.walletconnect.network\";\n\n/** Time constants */\nexport const ONE_WEEK_IN_SECONDS = 604800;\n\n/** WCT token decimals */\nexport const WCT_DECIMALS = 18;\n\n/** APY formula constants (from math.ts) */\nexport const APY_SLOPE = -0.06464;\nexport const APY_INTERCEPT = 12.0808;\nexport const APY_STAKE_WEIGHT_DIVISOR = 1_000_000;\nexport const MAX_LOCK_WEEKS = 104;\n\n/** CLI metadata for WalletConnect pairing */\nexport const CLI_METADATA = {\n name: \"walletconnect-staking\",\n description: \"WalletConnect WCT Staking CLI\",\n url: \"https://walletconnect.com\",\n icons: [],\n};\n","import { encodeFunctionData, parseAbi } from \"viem\";\nimport {\n L2_WCT_ADDRESS,\n STAKE_WEIGHT_ADDRESS,\n STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n} from \"./constants.js\";\n\n// ---- ABI fragments ---------------------------------------------------- //\n\nconst erc20Abi = parseAbi([\n \"function approve(address spender, uint256 value) returns (bool)\",\n \"function balanceOf(address account) view returns (uint256)\",\n \"function allowance(address owner, address spender) view returns (uint256)\",\n]);\n\nconst stakeWeightAbi = parseAbi([\n \"function createLock(uint256 amount, uint256 unlockTime)\",\n \"function updateLock(uint256 amount, uint256 unlockTime)\",\n \"function increaseLockAmount(uint256 amount)\",\n \"function increaseUnlockTime(uint256 newUnlockTime)\",\n \"function withdrawAll()\",\n \"function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)\",\n]);\n\nconst stakingRewardDistributorAbi = parseAbi([\n \"function claim(address user) returns (uint256)\",\n]);\n\n// ---- Transaction builders --------------------------------------------- //\n\nexport interface TxData {\n to: string;\n data: string;\n}\n\nexport function buildApprove(spender: string, amount: bigint): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender as `0x${string}`, amount],\n }),\n };\n}\n\nexport function buildCreateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"createLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildUpdateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"updateLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildIncreaseLockAmount(amount: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseLockAmount\",\n args: [amount],\n }),\n };\n}\n\nexport function buildIncreaseUnlockTime(newUnlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseUnlockTime\",\n args: [newUnlockTime],\n }),\n };\n}\n\nexport function buildWithdrawAll(): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"withdrawAll\",\n }),\n };\n}\n\nexport function buildClaim(user: string): TxData {\n return {\n to: STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n data: encodeFunctionData({\n abi: stakingRewardDistributorAbi,\n functionName: \"claim\",\n args: [user as `0x${string}`],\n }),\n };\n}\n\n// ---- Call data builders (for eth_call) -------------------------------- //\n\nexport function buildBalanceOfCallData(account: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [account as `0x${string}`],\n }),\n };\n}\n\nexport function buildAllowanceCallData(owner: string, spender: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [owner as `0x${string}`, spender as `0x${string}`],\n }),\n };\n}\n\nexport function buildLocksCallData(account: string): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"locks\",\n args: [account as `0x${string}`],\n }),\n };\n}\n","import { decodeAbiParameters } from \"viem\";\nimport { OPTIMISM_RPC_URL } from \"./constants.js\";\nimport type { TxData } from \"./contracts.js\";\n\nlet requestId = 1;\n\nasync function rpcRequest<T = string>(\n method: string,\n params: unknown[],\n rpcUrl: string,\n): Promise<T> {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: requestId++,\n method,\n params,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`RPC request failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as { result?: T; error?: { message: string } };\n\n if (json.error) {\n throw new Error(`RPC error: ${json.error.message}`);\n }\n\n return json.result!;\n}\n\nasync function ethCall(tx: TxData, rpcUrl: string): Promise<string> {\n return rpcRequest(\"eth_call\", [{ to: tx.to, data: tx.data }, \"latest\"], rpcUrl);\n}\n\n/** Read a uint256 from an eth_call result */\nexport async function readUint256(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<bigint> {\n const result = await ethCall(tx, rpcUrl);\n const [value] = decodeAbiParameters([{ type: \"uint256\" }], result as `0x${string}`);\n return value;\n}\n\n/** Estimate gas for a transaction, with a 20% buffer */\nexport async function estimateGas(\n from: string,\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<string> {\n const result = await rpcRequest(\n \"eth_estimateGas\",\n [{ from, to: tx.to, data: tx.data, value: \"0x0\" }, \"latest\"],\n rpcUrl,\n );\n // Add 20% buffer to the estimate\n const estimate = BigInt(result);\n const buffered = estimate + estimate / 5n;\n return `0x${buffered.toString(16)}`;\n}\n\ninterface TxReceipt {\n status: string;\n blockNumber: string;\n transactionHash: string;\n}\n\n/** Wait for a transaction to be confirmed (polls eth_getTransactionReceipt) */\nexport async function waitForTx(\n txHash: string,\n rpcUrl: string = OPTIMISM_RPC_URL,\n { intervalMs = 2000, timeoutMs = 60000 } = {},\n): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const receipt = await rpcRequest<TxReceipt | null>(\n \"eth_getTransactionReceipt\",\n [txHash],\n rpcUrl,\n );\n if (receipt) {\n if (receipt.status === \"0x0\") {\n throw new Error(`Transaction ${txHash} reverted`);\n }\n return;\n }\n } catch (err) {\n // Re-throw revert errors, swallow \"receipt not available yet\"\n if (err instanceof Error && err.message.includes(\"reverted\")) throw err;\n }\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n throw new Error(`Transaction ${txHash} not confirmed within ${timeoutMs / 1000}s`);\n}\n\n/** Read the locks() return: (int128 amount, uint256 end, uint256 transferredAmount) */\nexport async function readLocks(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<{ amount: bigint; end: bigint; transferredAmount: bigint }> {\n const result = await ethCall(tx, rpcUrl);\n const [amount, end, transferredAmount] = decodeAbiParameters(\n [{ type: \"int128\" }, { type: \"uint256\" }, { type: \"uint256\" }],\n result as `0x${string}`,\n );\n return { amount: BigInt(amount), end, transferredAmount };\n}\n","import { FOUNDATION_API_URL } from \"./constants.js\";\n\nexport interface StakingPosition {\n isPermanent: boolean;\n amount: string;\n createdAt: string;\n unlocksAt?: string;\n duration?: string;\n}\n\nexport interface StakingRewards {\n amount: string;\n}\n\nexport interface StakingResponse {\n position: StakingPosition | null;\n rewards: StakingRewards | null;\n}\n\nexport interface StakeWeightResponse {\n stakeWeight: string;\n}\n\nfunction getBaseUrl(): string {\n return process.env.FOUNDATION_API_URL || FOUNDATION_API_URL;\n}\n\nexport async function fetchStaking(address: string): Promise<StakingResponse> {\n const url = `${getBaseUrl()}/staking?address=${address}`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakingResponse;\n}\n\nexport async function fetchStakeWeight(): Promise<StakeWeightResponse> {\n const url = `${getBaseUrl()}/stake-weight`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakeWeightResponse;\n}\n","import { formatUnits } from \"viem\";\nimport {\n WCT_DECIMALS,\n APY_SLOPE,\n APY_INTERCEPT,\n APY_STAKE_WEIGHT_DIVISOR,\n MAX_LOCK_WEEKS,\n} from \"./constants.js\";\n\n/** Format a bigint WCT amount as a human-readable string with 2 decimals */\nexport function formatWCT(amount: bigint): string {\n const raw = formatUnits(amount, WCT_DECIMALS);\n const num = parseFloat(raw);\n return num.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\n/** Format a unix timestamp as a locale date string */\nexport function formatDate(timestamp: number): string {\n return new Date(timestamp * 1000).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Calculate base APY from total stake weight (from math.ts) */\nexport function calculateAPY(stakeWeight: number): number {\n return Math.max(\n (stakeWeight / APY_STAKE_WEIGHT_DIVISOR) * APY_SLOPE + APY_INTERCEPT,\n 0,\n );\n}\n\n/** Calculate weekly APY adjusted for lock duration */\nexport function calculateWeeklyAPY(baseAPY: number, weeks: number): number {\n return baseAPY * (Math.min(weeks, MAX_LOCK_WEEKS) / 52);\n}\n\n/** Print a labeled key-value pair */\nexport function label(key: string, value: string): string {\n return ` ${key.padEnd(12)} ${value}`;\n}\n"],"mappings":"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","names":["index_exports","__export","CAIP2_CHAIN_ID","CHAIN_ID","CLI_METADATA","L2_WCT_ADDRESS","STAKE_WEIGHT_ADDRESS","STAKING_REWARD_DISTRIBUTOR_ADDRESS","balance","buildAllowanceCallData","buildApprove","buildBalanceOfCallData","buildClaim","buildCreateLock","buildIncreaseLockAmount","buildIncreaseUnlockTime","buildLocksCallData","buildUpdateLock","buildWithdrawAll","calculateAPY","calculateWeeklyAPY","claim","fetchStakeWeight","fetchStaking","formatDate","formatWCT","stake","status","unstake","__toCommonJS","import_viem","CHAIN_ID","CAIP2_CHAIN_ID","L2_WCT_ADDRESS","STAKE_WEIGHT_ADDRESS","STAKING_REWARD_DISTRIBUTOR_ADDRESS","OPTIMISM_RPC_URL","FOUNDATION_API_URL","CLI_METADATA","import_viem","erc20Abi","stakeWeightAbi","stakingRewardDistributorAbi","buildApprove","spender","amount","L2_WCT_ADDRESS","buildCreateLock","unlockTime","STAKE_WEIGHT_ADDRESS","buildUpdateLock","buildIncreaseLockAmount","buildIncreaseUnlockTime","newUnlockTime","buildWithdrawAll","buildClaim","user","STAKING_REWARD_DISTRIBUTOR_ADDRESS","buildBalanceOfCallData","account","buildAllowanceCallData","owner","buildLocksCallData","import_viem","requestId","rpcRequest","method","params","rpcUrl","res","json","ethCall","tx","readUint256","OPTIMISM_RPC_URL","result","value","estimateGas","from","estimate","waitForTx","txHash","intervalMs","timeoutMs","start","receipt","err","r","readLocks","amount","end","transferredAmount","getBaseUrl","FOUNDATION_API_URL","fetchStaking","address","url","res","fetchStakeWeight","import_viem","formatWCT","amount","raw","formatDate","timestamp","calculateAPY","stakeWeight","calculateWeeklyAPY","baseAPY","weeks","label","key","value","computeUnlockTime","weeks","now","sendTx","wallet","from","tx","gas","estimateGas","CAIP2_CHAIN_ID","stake","address","amount","amountWei","requestedUnlockTime","lock","readLocks","buildLocksCallData","hasPosition","label","formatWCT","formatDate","effectiveUnlockTime","extendingTime","readUint256","buildAllowanceCallData","STAKE_WEIGHT_ADDRESS","approveTxHash","buildApprove","waitForTx","txHash","buildUpdateLock","buildIncreaseLockAmount","buildCreateLock","unstake","staking","fetchStaking","unlocksAt","buildWithdrawAll","claim","buildClaim","status","stakeWeightRes","fetchStakeWeight","pos","durationWeeks","stakeWeight","baseAPY","calculateAPY","weeklyAPY","calculateWeeklyAPY","balance","bal","buildBalanceOfCallData"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands.ts","../src/constants.ts","../src/contracts.ts","../src/rpc.ts","../src/api.ts","../src/format.ts"],"sourcesContent":["export { stake, unstake, claim, status, balance } from \"./commands.js\";\nexport { formatWCT, formatDate, calculateAPY, calculateWeeklyAPY } from \"./format.js\";\nexport { fetchStaking, fetchStakeWeight } from \"./api.js\";\nexport type { StakingPosition, StakingRewards, StakingResponse, StakeWeightResponse } from \"./api.js\";\nexport {\n buildApprove,\n buildCreateLock,\n buildUpdateLock,\n buildIncreaseLockAmount,\n buildIncreaseUnlockTime,\n buildWithdrawAll,\n buildClaim,\n buildBalanceOfCallData,\n buildAllowanceCallData,\n buildLocksCallData,\n} from \"./contracts.js\";\nexport type { TxData } from \"./contracts.js\";\nexport {\n CHAIN_ID,\n CAIP2_CHAIN_ID,\n L2_WCT_ADDRESS,\n STAKE_WEIGHT_ADDRESS,\n STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n CLI_METADATA,\n} from \"./constants.js\";\n","import { parseUnits } from \"viem\";\nimport type { WalletConnectCLI } from \"@walletconnect/cli-sdk\";\nimport {\n CAIP2_CHAIN_ID,\n STAKE_WEIGHT_ADDRESS,\n ONE_WEEK_IN_SECONDS,\n MIN_REMAINING_LOCK_SECONDS,\n WCT_DECIMALS,\n} from \"./constants.js\";\nimport {\n buildApprove,\n buildCreateLock,\n buildUpdateLock,\n buildIncreaseLockAmount,\n buildWithdrawAll,\n buildClaim,\n buildBalanceOfCallData,\n buildAllowanceCallData,\n buildLocksCallData,\n type TxData,\n} from \"./contracts.js\";\nimport { readUint256, readLocks, estimateGas, waitForTx } from \"./rpc.js\";\nimport { fetchStaking, fetchStakeWeight } from \"./api.js\";\nimport { formatWCT, formatDate, calculateAPY, calculateWeeklyAPY, label } from \"./format.js\";\n\n// ---- Helpers ---------------------------------------------------------- //\n\nfunction computeUnlockTime(weeks: number): bigint {\n const now = Math.floor(Date.now() / 1000);\n return (BigInt(Math.floor((now + weeks * ONE_WEEK_IN_SECONDS) / ONE_WEEK_IN_SECONDS)) *\n BigInt(ONE_WEEK_IN_SECONDS));\n}\n\nasync function sendTx(\n wallet: WalletConnectCLI,\n from: string,\n tx: TxData,\n): Promise<string> {\n const gas = await estimateGas(from, tx);\n return wallet.request<string>({\n chainId: CAIP2_CHAIN_ID,\n request: {\n method: \"eth_sendTransaction\",\n params: [{ from, to: tx.to, data: tx.data, value: \"0x0\", gas }],\n },\n });\n}\n\n// ---- Commands --------------------------------------------------------- //\n\nexport async function stake(\n wallet: WalletConnectCLI,\n address: string,\n amount: string,\n weeks: number,\n): Promise<void> {\n const amountWei = parseUnits(amount, WCT_DECIMALS);\n const requestedUnlockTime = computeUnlockTime(weeks);\n\n // Read on-chain position to determine the right action\n const lock = await readLocks(buildLocksCallData(address));\n const hasPosition = lock.amount > 0n;\n\n if (hasPosition) {\n console.log(\"\\nExisting staking position:\");\n console.log(label(\"Staked\", `${formatWCT(BigInt(lock.amount))} WCT`));\n console.log(label(\"Unlocks\", formatDate(Number(lock.end))));\n }\n\n // Determine effective unlock time — never shorten an existing lock\n let effectiveUnlockTime = requestedUnlockTime;\n const extendingTime = !hasPosition || requestedUnlockTime > lock.end;\n\n if (hasPosition && requestedUnlockTime <= lock.end) {\n effectiveUnlockTime = lock.end;\n console.log(`\\nRequested unlock (${formatDate(Number(requestedUnlockTime))}) is before existing lock end.`);\n console.log(`Keeping current unlock date: ${formatDate(Number(lock.end))}`);\n }\n\n console.log(`\\nAdding ${amount} WCT${extendingTime ? `, extending lock to ${formatDate(Number(effectiveUnlockTime))}` : \"\"}...`);\n\n // Check allowance and approve if needed\n const allowance = await readUint256(buildAllowanceCallData(address, STAKE_WEIGHT_ADDRESS));\n if (allowance < amountWei) {\n console.log(\"\\nApproving WCT spend...\");\n const approveTxHash = await sendTx(wallet, address, buildApprove(STAKE_WEIGHT_ADDRESS, amountWei));\n console.log(label(\"Approve tx\", approveTxHash));\n console.log(\"Waiting for confirmation...\");\n await waitForTx(approveTxHash);\n }\n\n let txHash: string;\n\n if (!hasPosition) {\n console.log(\"\\nCreating new lock...\");\n txHash = await sendTx(wallet, address, buildCreateLock(amountWei, effectiveUnlockTime));\n } else if (extendingTime) {\n console.log(\"\\nUpdating lock (amount + time)...\");\n txHash = await sendTx(wallet, address, buildUpdateLock(amountWei, effectiveUnlockTime));\n } else {\n const now = BigInt(Math.floor(Date.now() / 1000));\n const remaining = lock.end - now;\n\n if (remaining < BigInt(MIN_REMAINING_LOCK_SECONDS)) {\n const days = Number(remaining) / 86400;\n console.error(\n `\\nCannot add to position: lock expires in ~${Math.ceil(days)} day(s), ` +\n `which is below the minimum remaining period of 1 week.\\n` +\n `Re-run with a longer --weeks value to extend your lock.`,\n );\n return;\n }\n\n console.log(\"\\nIncreasing lock amount...\");\n txHash = await sendTx(wallet, address, buildIncreaseLockAmount(amountWei));\n }\n\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nStake submitted successfully.\");\n}\n\nexport async function unstake(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.position) {\n console.log(\"\\nNo staking position found.\");\n return;\n }\n\n if (staking.position.unlocksAt) {\n const unlocksAt = new Date(staking.position.unlocksAt).getTime() / 1000;\n const now = Math.floor(Date.now() / 1000);\n if (unlocksAt > now) {\n console.log(`\\nLock has not expired yet. Unlocks ${formatDate(unlocksAt)}.`);\n return;\n }\n }\n\n console.log(\"\\nWithdrawing all staked WCT...\");\n const txHash = await sendTx(wallet, address, buildWithdrawAll());\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nUnstake submitted successfully.\");\n}\n\nexport async function claim(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.rewards || staking.rewards.amount === \"0\") {\n console.log(\"\\nNo rewards to claim.\");\n return;\n }\n\n console.log(`\\nClaiming ${staking.rewards.amount} WCT in rewards...`);\n const txHash = await sendTx(wallet, address, buildClaim(address));\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nClaim submitted successfully.\");\n}\n\nexport async function status(address: string): Promise<void> {\n const [staking, stakeWeightRes] = await Promise.all([\n fetchStaking(address),\n fetchStakeWeight(),\n ]);\n\n console.log(`\\nStaking status for ${address}\\n`);\n\n if (!staking.position) {\n console.log(\" No staking position found.\\n\");\n } else {\n const pos = staking.position;\n console.log(label(\"Amount\", `${pos.amount} WCT`));\n console.log(label(\"Permanent\", pos.isPermanent ? \"Yes\" : \"No\"));\n console.log(label(\"Created\", new Date(pos.createdAt).toLocaleDateString(\"en-US\")));\n if (pos.unlocksAt) {\n console.log(label(\"Unlocks\", new Date(pos.unlocksAt).toLocaleDateString(\"en-US\")));\n }\n if (pos.duration) {\n const durationWeeks = Math.round(parseInt(pos.duration, 10) / ONE_WEEK_IN_SECONDS);\n console.log(label(\"Duration\", `${durationWeeks} week(s)`));\n }\n console.log();\n }\n\n if (staking.rewards) {\n console.log(label(\"Rewards\", `${staking.rewards.amount} WCT`));\n }\n\n const stakeWeight = parseFloat(stakeWeightRes.stakeWeight);\n const baseAPY = calculateAPY(stakeWeight);\n console.log(label(\"Base APY\", `${baseAPY.toFixed(2)}%`));\n\n if (staking.position?.duration) {\n const weeks = Math.round(parseInt(staking.position.duration, 10) / ONE_WEEK_IN_SECONDS);\n const weeklyAPY = calculateWeeklyAPY(baseAPY, weeks);\n console.log(label(\"Your APY\", `${weeklyAPY.toFixed(2)}%`));\n }\n\n console.log();\n}\n\nexport async function balance(address: string): Promise<void> {\n const bal = await readUint256(buildBalanceOfCallData(address));\n console.log(`\\n${label(\"WCT balance\", `${formatWCT(bal)} WCT`)}\\n`);\n}\n","/** Optimism chain ID */\nexport const CHAIN_ID = 10;\nexport const CAIP2_CHAIN_ID = \"eip155:10\";\n\n/** Contract addresses on Optimism */\nexport const L2_WCT_ADDRESS = \"0xeF4461891DfB3AC8572cCf7C794664A8DD927945\";\nexport const STAKE_WEIGHT_ADDRESS = \"0x521B4C065Bbdbe3E20B3727340730936912DfA46\";\nexport const STAKING_REWARD_DISTRIBUTOR_ADDRESS = \"0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF\";\n\n/** Public Optimism RPC endpoint */\nexport const OPTIMISM_RPC_URL = \"https://mainnet.optimism.io\";\n\n/** Foundation API */\nexport const FOUNDATION_API_URL = \"https://api.walletconnect.network\";\n\n/** Time constants */\nexport const ONE_WEEK_IN_SECONDS = 604800;\n\n/** Minimum remaining lock time required to increase lock amount (1 week) */\nexport const MIN_REMAINING_LOCK_SECONDS = ONE_WEEK_IN_SECONDS;\n\n/** WCT token decimals */\nexport const WCT_DECIMALS = 18;\n\n/** APY formula constants (from math.ts) */\nexport const APY_SLOPE = -0.06464;\nexport const APY_INTERCEPT = 12.0808;\nexport const APY_STAKE_WEIGHT_DIVISOR = 1_000_000;\nexport const MAX_LOCK_WEEKS = 104;\n\n/** CLI metadata for WalletConnect pairing */\nexport const CLI_METADATA = {\n name: \"walletconnect-staking\",\n description: \"WalletConnect WCT Staking CLI\",\n url: \"https://walletconnect.com\",\n icons: [],\n};\n","import { encodeFunctionData, parseAbi } from \"viem\";\nimport {\n L2_WCT_ADDRESS,\n STAKE_WEIGHT_ADDRESS,\n STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n} from \"./constants.js\";\n\n// ---- ABI fragments ---------------------------------------------------- //\n\nconst erc20Abi = parseAbi([\n \"function approve(address spender, uint256 value) returns (bool)\",\n \"function balanceOf(address account) view returns (uint256)\",\n \"function allowance(address owner, address spender) view returns (uint256)\",\n]);\n\nconst stakeWeightAbi = parseAbi([\n \"function createLock(uint256 amount, uint256 unlockTime)\",\n \"function updateLock(uint256 amount, uint256 unlockTime)\",\n \"function increaseLockAmount(uint256 amount)\",\n \"function increaseUnlockTime(uint256 newUnlockTime)\",\n \"function withdrawAll()\",\n \"function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)\",\n]);\n\nconst stakingRewardDistributorAbi = parseAbi([\n \"function claim(address user) returns (uint256)\",\n]);\n\n// ---- Transaction builders --------------------------------------------- //\n\nexport interface TxData {\n to: string;\n data: string;\n}\n\nexport function buildApprove(spender: string, amount: bigint): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender as `0x${string}`, amount],\n }),\n };\n}\n\nexport function buildCreateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"createLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildUpdateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"updateLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildIncreaseLockAmount(amount: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseLockAmount\",\n args: [amount],\n }),\n };\n}\n\nexport function buildIncreaseUnlockTime(newUnlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseUnlockTime\",\n args: [newUnlockTime],\n }),\n };\n}\n\nexport function buildWithdrawAll(): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"withdrawAll\",\n }),\n };\n}\n\nexport function buildClaim(user: string): TxData {\n return {\n to: STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n data: encodeFunctionData({\n abi: stakingRewardDistributorAbi,\n functionName: \"claim\",\n args: [user as `0x${string}`],\n }),\n };\n}\n\n// ---- Call data builders (for eth_call) -------------------------------- //\n\nexport function buildBalanceOfCallData(account: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [account as `0x${string}`],\n }),\n };\n}\n\nexport function buildAllowanceCallData(owner: string, spender: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [owner as `0x${string}`, spender as `0x${string}`],\n }),\n };\n}\n\nexport function buildLocksCallData(account: string): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"locks\",\n args: [account as `0x${string}`],\n }),\n };\n}\n","import { decodeAbiParameters } from \"viem\";\nimport { OPTIMISM_RPC_URL } from \"./constants.js\";\nimport type { TxData } from \"./contracts.js\";\n\nlet requestId = 1;\n\nasync function rpcRequest<T = string>(\n method: string,\n params: unknown[],\n rpcUrl: string,\n): Promise<T> {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: requestId++,\n method,\n params,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`RPC request failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as { result?: T; error?: { message: string } };\n\n if (json.error) {\n throw new Error(`RPC error: ${json.error.message}`);\n }\n\n return json.result!;\n}\n\nasync function ethCall(tx: TxData, rpcUrl: string): Promise<string> {\n return rpcRequest(\"eth_call\", [{ to: tx.to, data: tx.data }, \"latest\"], rpcUrl);\n}\n\n/** Read a uint256 from an eth_call result */\nexport async function readUint256(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<bigint> {\n const result = await ethCall(tx, rpcUrl);\n const [value] = decodeAbiParameters([{ type: \"uint256\" }], result as `0x${string}`);\n return value;\n}\n\n/** Estimate gas for a transaction, with a 20% buffer */\nexport async function estimateGas(\n from: string,\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<string> {\n const result = await rpcRequest(\n \"eth_estimateGas\",\n [{ from, to: tx.to, data: tx.data, value: \"0x0\" }, \"latest\"],\n rpcUrl,\n );\n // Add 20% buffer to the estimate\n const estimate = BigInt(result);\n const buffered = estimate + estimate / 5n;\n return `0x${buffered.toString(16)}`;\n}\n\ninterface TxReceipt {\n status: string;\n blockNumber: string;\n transactionHash: string;\n}\n\n/** Wait for a transaction to be confirmed (polls eth_getTransactionReceipt) */\nexport async function waitForTx(\n txHash: string,\n rpcUrl: string = OPTIMISM_RPC_URL,\n { intervalMs = 2000, timeoutMs = 60000 } = {},\n): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const receipt = await rpcRequest<TxReceipt | null>(\n \"eth_getTransactionReceipt\",\n [txHash],\n rpcUrl,\n );\n if (receipt) {\n if (receipt.status === \"0x0\") {\n throw new Error(`Transaction ${txHash} reverted`);\n }\n return;\n }\n } catch (err) {\n // Re-throw revert errors, swallow \"receipt not available yet\"\n if (err instanceof Error && err.message.includes(\"reverted\")) throw err;\n }\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n throw new Error(`Transaction ${txHash} not confirmed within ${timeoutMs / 1000}s`);\n}\n\n/** Read the locks() return: (int128 amount, uint256 end, uint256 transferredAmount) */\nexport async function readLocks(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<{ amount: bigint; end: bigint; transferredAmount: bigint }> {\n const result = await ethCall(tx, rpcUrl);\n const [amount, end, transferredAmount] = decodeAbiParameters(\n [{ type: \"int128\" }, { type: \"uint256\" }, { type: \"uint256\" }],\n result as `0x${string}`,\n );\n return { amount: BigInt(amount), end, transferredAmount };\n}\n","import { FOUNDATION_API_URL } from \"./constants.js\";\n\nexport interface StakingPosition {\n isPermanent: boolean;\n amount: string;\n createdAt: string;\n unlocksAt?: string;\n duration?: string;\n}\n\nexport interface StakingRewards {\n amount: string;\n}\n\nexport interface StakingResponse {\n position: StakingPosition | null;\n rewards: StakingRewards | null;\n}\n\nexport interface StakeWeightResponse {\n stakeWeight: string;\n}\n\nfunction getBaseUrl(): string {\n return process.env.FOUNDATION_API_URL || FOUNDATION_API_URL;\n}\n\nexport async function fetchStaking(address: string): Promise<StakingResponse> {\n const url = `${getBaseUrl()}/staking?address=${address}`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakingResponse;\n}\n\nexport async function fetchStakeWeight(): Promise<StakeWeightResponse> {\n const url = `${getBaseUrl()}/stake-weight`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakeWeightResponse;\n}\n","import { formatUnits } from \"viem\";\nimport {\n WCT_DECIMALS,\n APY_SLOPE,\n APY_INTERCEPT,\n APY_STAKE_WEIGHT_DIVISOR,\n MAX_LOCK_WEEKS,\n} from \"./constants.js\";\n\n/** Format a bigint WCT amount as a human-readable string with 2 decimals */\nexport function formatWCT(amount: bigint): string {\n const raw = formatUnits(amount, WCT_DECIMALS);\n const num = parseFloat(raw);\n return num.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\n/** Format a unix timestamp as a locale date string */\nexport function formatDate(timestamp: number): string {\n return new Date(timestamp * 1000).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Calculate base APY from total stake weight (from math.ts) */\nexport function calculateAPY(stakeWeight: number): number {\n return Math.max(\n (stakeWeight / APY_STAKE_WEIGHT_DIVISOR) * APY_SLOPE + APY_INTERCEPT,\n 0,\n );\n}\n\n/** Calculate weekly APY adjusted for lock duration */\nexport function calculateWeeklyAPY(baseAPY: number, weeks: number): number {\n return baseAPY * (Math.min(weeks, MAX_LOCK_WEEKS) / 52);\n}\n\n/** Print a labeled key-value pair */\nexport function label(key: string, value: string): string {\n return ` ${key.padEnd(12)} ${value}`;\n}\n"],"mappings":"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","names":["index_exports","__export","CAIP2_CHAIN_ID","CHAIN_ID","CLI_METADATA","L2_WCT_ADDRESS","STAKE_WEIGHT_ADDRESS","STAKING_REWARD_DISTRIBUTOR_ADDRESS","balance","buildAllowanceCallData","buildApprove","buildBalanceOfCallData","buildClaim","buildCreateLock","buildIncreaseLockAmount","buildIncreaseUnlockTime","buildLocksCallData","buildUpdateLock","buildWithdrawAll","calculateAPY","calculateWeeklyAPY","claim","fetchStakeWeight","fetchStaking","formatDate","formatWCT","stake","status","unstake","__toCommonJS","import_viem","CHAIN_ID","CAIP2_CHAIN_ID","L2_WCT_ADDRESS","STAKE_WEIGHT_ADDRESS","STAKING_REWARD_DISTRIBUTOR_ADDRESS","OPTIMISM_RPC_URL","FOUNDATION_API_URL","CLI_METADATA","import_viem","erc20Abi","stakeWeightAbi","stakingRewardDistributorAbi","buildApprove","spender","amount","L2_WCT_ADDRESS","buildCreateLock","unlockTime","STAKE_WEIGHT_ADDRESS","buildUpdateLock","buildIncreaseLockAmount","buildIncreaseUnlockTime","newUnlockTime","buildWithdrawAll","buildClaim","user","STAKING_REWARD_DISTRIBUTOR_ADDRESS","buildBalanceOfCallData","account","buildAllowanceCallData","owner","buildLocksCallData","import_viem","requestId","rpcRequest","method","params","rpcUrl","res","json","ethCall","tx","readUint256","OPTIMISM_RPC_URL","result","value","estimateGas","from","estimate","waitForTx","txHash","intervalMs","timeoutMs","start","receipt","err","r","readLocks","amount","end","transferredAmount","getBaseUrl","FOUNDATION_API_URL","fetchStaking","address","url","res","fetchStakeWeight","import_viem","formatWCT","amount","raw","formatDate","timestamp","calculateAPY","stakeWeight","calculateWeeklyAPY","baseAPY","weeks","label","key","value","computeUnlockTime","weeks","now","sendTx","wallet","from","tx","gas","estimateGas","CAIP2_CHAIN_ID","stake","address","amount","amountWei","requestedUnlockTime","lock","readLocks","buildLocksCallData","hasPosition","label","formatWCT","formatDate","effectiveUnlockTime","extendingTime","readUint256","buildAllowanceCallData","STAKE_WEIGHT_ADDRESS","approveTxHash","buildApprove","waitForTx","txHash","buildCreateLock","buildUpdateLock","remaining","days","buildIncreaseLockAmount","unstake","staking","fetchStaking","unlocksAt","buildWithdrawAll","claim","buildClaim","status","stakeWeightRes","fetchStakeWeight","pos","durationWeeks","stakeWeight","baseAPY","calculateAPY","weeklyAPY","calculateWeeklyAPY","balance","bal","buildBalanceOfCallData"]}
package/dist/index.js CHANGED
@@ -1,22 +1,24 @@
1
- import{parseUnits as nt}from"viem";var X=10,D="eip155:10",d="0xeF4461891DfB3AC8572cCf7C794664A8DD927945",c="0x521B4C065Bbdbe3E20B3727340730936912DfA46",b="0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF",f="https://mainnet.optimism.io",B="https://api.walletconnect.network";var J={name:"walletconnect-staking",description:"WalletConnect WCT Staking CLI",url:"https://walletconnect.com",icons:[]};import{encodeFunctionData as l,parseAbi as S}from"viem";var C=S(["function approve(address spender, uint256 value) returns (bool)","function balanceOf(address account) view returns (uint256)","function allowance(address owner, address spender) view returns (uint256)"]),g=S(["function createLock(uint256 amount, uint256 unlockTime)","function updateLock(uint256 amount, uint256 unlockTime)","function increaseLockAmount(uint256 amount)","function increaseUnlockTime(uint256 newUnlockTime)","function withdrawAll()","function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)"]),z=S(["function claim(address user) returns (uint256)"]);function I(t,n){return{to:d,data:l({abi:C,functionName:"approve",args:[t,n]})}}function _(t,n){return{to:c,data:l({abi:g,functionName:"createLock",args:[t,n]})}}function h(t,n){return{to:c,data:l({abi:g,functionName:"updateLock",args:[t,n]})}}function W(t){return{to:c,data:l({abi:g,functionName:"increaseLockAmount",args:[t]})}}function Q(t){return{to:c,data:l({abi:g,functionName:"increaseUnlockTime",args:[t]})}}function P(){return{to:c,data:l({abi:g,functionName:"withdrawAll"})}}function E(t){return{to:b,data:l({abi:z,functionName:"claim",args:[t]})}}function R(t){return{to:d,data:l({abi:C,functionName:"balanceOf",args:[t]})}}function L(t,n){return{to:d,data:l({abi:C,functionName:"allowance",args:[t,n]})}}function N(t){return{to:c,data:l({abi:g,functionName:"locks",args:[t]})}}import{decodeAbiParameters as M}from"viem";var Z=1;async function $(t,n,o){let a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:Z++,method:t,params:n})});if(!a.ok)throw new Error(`RPC request failed: ${a.status} ${a.statusText}`);let i=await a.json();if(i.error)throw new Error(`RPC error: ${i.error.message}`);return i.result}async function K(t,n){return $("eth_call",[{to:t.to,data:t.data},"latest"],n)}async function y(t,n=f){let o=await K(t,n),[a]=M([{type:"uint256"}],o);return a}async function H(t,n,o=f){let a=await $("eth_estimateGas",[{from:t,to:n.to,data:n.data,value:"0x0"},"latest"],o),i=BigInt(a);return`0x${(i+i/5n).toString(16)}`}async function G(t,n=f,{intervalMs:o=2e3,timeoutMs:a=6e4}={}){let i=Date.now();for(;Date.now()-i<a;){try{let e=await $("eth_getTransactionReceipt",[t],n);if(e){if(e.status==="0x0")throw new Error(`Transaction ${t} reverted`);return}}catch(e){if(e instanceof Error&&e.message.includes("reverted"))throw e}await new Promise(e=>setTimeout(e,o))}throw new Error(`Transaction ${t} not confirmed within ${a/1e3}s`)}async function j(t,n=f){let o=await K(t,n),[a,i,e]=M([{type:"int128"},{type:"uint256"},{type:"uint256"}],o);return{amount:BigInt(a),end:i,transferredAmount:e}}function q(){return process.env.FOUNDATION_API_URL||B}async function p(t){let n=`${q()}/staking?address=${t}`,o=await fetch(n);if(!o.ok)throw new Error(`Foundation API error: ${o.status} ${o.statusText}`);return await o.json()}async function U(){let t=`${q()}/stake-weight`,n=await fetch(t);if(!n.ok)throw new Error(`Foundation API error: ${n.status} ${n.statusText}`);return await n.json()}import{formatUnits as tt}from"viem";function w(t){let n=tt(t,18);return parseFloat(n).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}function u(t){return new Date(t*1e3).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function O(t){return Math.max(t/1e6*-.06464+12.0808,0)}function v(t,n){return t*(Math.min(n,104)/52)}function r(t,n){return` ${t.padEnd(12)} ${n}`}function ot(t){let n=Math.floor(Date.now()/1e3);return BigInt(Math.floor((n+t*604800)/604800))*BigInt(604800)}async function m(t,n,o){let a=await H(n,o);return t.request({chainId:D,request:{method:"eth_sendTransaction",params:[{from:n,to:o.to,data:o.data,value:"0x0",gas:a}]}})}async function et(t,n,o,a){let i=nt(o,18),e=ot(a),s=await j(N(n)),A=s.amount>0n;A&&(console.log(`
2
- Existing staking position:`),console.log(r("Staked",`${w(BigInt(s.amount))} WCT`)),console.log(r("Unlocks",u(Number(s.end)))));let T=e,F=!A||e>s.end;if(A&&e<=s.end&&(T=s.end,console.log(`
1
+ import{parseUnits as at}from"viem";var z=10,b="eip155:10",d="0xeF4461891DfB3AC8572cCf7C794664A8DD927945",c="0x521B4C065Bbdbe3E20B3727340730936912DfA46",S="0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF",p="https://mainnet.optimism.io",K="https://api.walletconnect.network";var Q={name:"walletconnect-staking",description:"WalletConnect WCT Staking CLI",url:"https://walletconnect.com",icons:[]};import{encodeFunctionData as l,parseAbi as C}from"viem";var I=C(["function approve(address spender, uint256 value) returns (bool)","function balanceOf(address account) view returns (uint256)","function allowance(address owner, address spender) view returns (uint256)"]),g=C(["function createLock(uint256 amount, uint256 unlockTime)","function updateLock(uint256 amount, uint256 unlockTime)","function increaseLockAmount(uint256 amount)","function increaseUnlockTime(uint256 newUnlockTime)","function withdrawAll()","function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)"]),Z=C(["function claim(address user) returns (uint256)"]);function _(t,n){return{to:d,data:l({abi:I,functionName:"approve",args:[t,n]})}}function h(t,n){return{to:c,data:l({abi:g,functionName:"createLock",args:[t,n]})}}function E(t,n){return{to:c,data:l({abi:g,functionName:"updateLock",args:[t,n]})}}function W(t){return{to:c,data:l({abi:g,functionName:"increaseLockAmount",args:[t]})}}function tt(t){return{to:c,data:l({abi:g,functionName:"increaseUnlockTime",args:[t]})}}function P(){return{to:c,data:l({abi:g,functionName:"withdrawAll"})}}function R(t){return{to:S,data:l({abi:Z,functionName:"claim",args:[t]})}}function N(t){return{to:d,data:l({abi:I,functionName:"balanceOf",args:[t]})}}function L(t,n){return{to:d,data:l({abi:I,functionName:"allowance",args:[t,n]})}}function $(t){return{to:c,data:l({abi:g,functionName:"locks",args:[t]})}}import{decodeAbiParameters as Y}from"viem";var nt=1;async function y(t,n,o){let a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:nt++,method:t,params:n})});if(!a.ok)throw new Error(`RPC request failed: ${a.status} ${a.statusText}`);let i=await a.json();if(i.error)throw new Error(`RPC error: ${i.error.message}`);return i.result}async function G(t,n){return y("eth_call",[{to:t.to,data:t.data},"latest"],n)}async function U(t,n=p){let o=await G(t,n),[a]=Y([{type:"uint256"}],o);return a}async function H(t,n,o=p){let a=await y("eth_estimateGas",[{from:t,to:n.to,data:n.data,value:"0x0"},"latest"],o),i=BigInt(a);return`0x${(i+i/5n).toString(16)}`}async function j(t,n=p,{intervalMs:o=2e3,timeoutMs:a=6e4}={}){let i=Date.now();for(;Date.now()-i<a;){try{let e=await y("eth_getTransactionReceipt",[t],n);if(e){if(e.status==="0x0")throw new Error(`Transaction ${t} reverted`);return}}catch(e){if(e instanceof Error&&e.message.includes("reverted"))throw e}await new Promise(e=>setTimeout(e,o))}throw new Error(`Transaction ${t} not confirmed within ${a/1e3}s`)}async function q(t,n=p){let o=await G(t,n),[a,i,e]=Y([{type:"int128"},{type:"uint256"},{type:"uint256"}],o);return{amount:BigInt(a),end:i,transferredAmount:e}}function V(){return process.env.FOUNDATION_API_URL||K}async function f(t){let n=`${V()}/staking?address=${t}`,o=await fetch(n);if(!o.ok)throw new Error(`Foundation API error: ${o.status} ${o.statusText}`);return await o.json()}async function O(){let t=`${V()}/stake-weight`,n=await fetch(t);if(!n.ok)throw new Error(`Foundation API error: ${n.status} ${n.statusText}`);return await n.json()}import{formatUnits as ot}from"viem";function D(t){let n=ot(t,18);return parseFloat(n).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}function u(t){return new Date(t*1e3).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function v(t){return Math.max(t/1e6*-.06464+12.0808,0)}function M(t,n){return t*(Math.min(n,104)/52)}function r(t,n){return` ${t.padEnd(12)} ${n}`}function it(t){let n=Math.floor(Date.now()/1e3);return BigInt(Math.floor((n+t*604800)/604800))*BigInt(604800)}async function m(t,n,o){let a=await H(n,o);return t.request({chainId:b,request:{method:"eth_sendTransaction",params:[{from:n,to:o.to,data:o.data,value:"0x0",gas:a}]}})}async function rt(t,n,o,a){let i=at(o,18),e=it(a),s=await q($(n)),x=s.amount>0n;x&&(console.log(`
2
+ Existing staking position:`),console.log(r("Staked",`${D(BigInt(s.amount))} WCT`)),console.log(r("Unlocks",u(Number(s.end)))));let A=e,F=!x||e>s.end;if(x&&e<=s.end&&(A=s.end,console.log(`
3
3
  Requested unlock (${u(Number(e))}) is before existing lock end.`),console.log(`Keeping current unlock date: ${u(Number(s.end))}`)),console.log(`
4
- Adding ${o} WCT${F?`, extending lock to ${u(Number(T))}`:""}...`),await y(L(n,c))<i){console.log(`
5
- Approving WCT spend...`);let Y=await m(t,n,I(c,i));console.log(r("Approve tx",Y)),console.log("Waiting for confirmation..."),await G(Y)}let x;A?F?(console.log(`
6
- Updating lock (amount + time)...`),x=await m(t,n,h(i,T))):(console.log(`
7
- Increasing lock amount...`),x=await m(t,n,W(i))):(console.log(`
8
- Creating new lock...`),x=await m(t,n,_(i,T))),console.log(r("Tx hash",x)),console.log(`
9
- Stake submitted successfully.`)}async function at(t,n){let o=await p(n);if(!o.position){console.log(`
4
+ Adding ${o} WCT${F?`, extending lock to ${u(Number(A))}`:""}...`),await U(L(n,c))<i){console.log(`
5
+ Approving WCT spend...`);let w=await m(t,n,_(c,i));console.log(r("Approve tx",w)),console.log("Waiting for confirmation..."),await j(w)}let T;if(!x)console.log(`
6
+ Creating new lock...`),T=await m(t,n,h(i,A));else if(F)console.log(`
7
+ Updating lock (amount + time)...`),T=await m(t,n,E(i,A));else{let w=BigInt(Math.floor(Date.now()/1e3)),B=s.end-w;if(B<BigInt(604800)){let J=Number(B)/86400;console.error(`
8
+ Cannot add to position: lock expires in ~${Math.ceil(J)} day(s), which is below the minimum remaining period of 1 week.
9
+ Re-run with a longer --weeks value to extend your lock.`);return}console.log(`
10
+ Increasing lock amount...`),T=await m(t,n,W(i))}console.log(r("Tx hash",T)),console.log(`
11
+ Stake submitted successfully.`)}async function st(t,n){let o=await f(n);if(!o.position){console.log(`
10
12
  No staking position found.`);return}if(o.position.unlocksAt){let i=new Date(o.position.unlocksAt).getTime()/1e3,e=Math.floor(Date.now()/1e3);if(i>e){console.log(`
11
13
  Lock has not expired yet. Unlocks ${u(i)}.`);return}}console.log(`
12
14
  Withdrawing all staked WCT...`);let a=await m(t,n,P());console.log(r("Tx hash",a)),console.log(`
13
- Unstake submitted successfully.`)}async function it(t,n){let o=await p(n);if(!o.rewards||o.rewards.amount==="0"){console.log(`
15
+ Unstake submitted successfully.`)}async function ct(t,n){let o=await f(n);if(!o.rewards||o.rewards.amount==="0"){console.log(`
14
16
  No rewards to claim.`);return}console.log(`
15
- Claiming ${o.rewards.amount} WCT in rewards...`);let a=await m(t,n,E(n));console.log(r("Tx hash",a)),console.log(`
16
- Claim submitted successfully.`)}async function rt(t){let[n,o]=await Promise.all([p(t),U()]);if(console.log(`
17
+ Claiming ${o.rewards.amount} WCT in rewards...`);let a=await m(t,n,R(n));console.log(r("Tx hash",a)),console.log(`
18
+ Claim submitted successfully.`)}async function lt(t){let[n,o]=await Promise.all([f(t),O()]);if(console.log(`
17
19
  Staking status for ${t}
18
20
  `),!n.position)console.log(` No staking position found.
19
- `);else{let e=n.position;if(console.log(r("Amount",`${e.amount} WCT`)),console.log(r("Permanent",e.isPermanent?"Yes":"No")),console.log(r("Created",new Date(e.createdAt).toLocaleDateString("en-US"))),e.unlocksAt&&console.log(r("Unlocks",new Date(e.unlocksAt).toLocaleDateString("en-US"))),e.duration){let s=Math.round(parseInt(e.duration,10)/604800);console.log(r("Duration",`${s} week(s)`))}console.log()}n.rewards&&console.log(r("Rewards",`${n.rewards.amount} WCT`));let a=parseFloat(o.stakeWeight),i=O(a);if(console.log(r("Base APY",`${i.toFixed(2)}%`)),n.position?.duration){let e=Math.round(parseInt(n.position.duration,10)/604800),s=v(i,e);console.log(r("Your APY",`${s.toFixed(2)}%`))}console.log()}async function st(t){let n=await y(R(t));console.log(`
20
- ${r("WCT balance",`${w(n)} WCT`)}
21
- `)}export{D as CAIP2_CHAIN_ID,X as CHAIN_ID,J as CLI_METADATA,d as L2_WCT_ADDRESS,c as STAKE_WEIGHT_ADDRESS,b as STAKING_REWARD_DISTRIBUTOR_ADDRESS,st as balance,L as buildAllowanceCallData,I as buildApprove,R as buildBalanceOfCallData,E as buildClaim,_ as buildCreateLock,W as buildIncreaseLockAmount,Q as buildIncreaseUnlockTime,N as buildLocksCallData,h as buildUpdateLock,P as buildWithdrawAll,O as calculateAPY,v as calculateWeeklyAPY,it as claim,U as fetchStakeWeight,p as fetchStaking,u as formatDate,w as formatWCT,et as stake,rt as status,at as unstake};
21
+ `);else{let e=n.position;if(console.log(r("Amount",`${e.amount} WCT`)),console.log(r("Permanent",e.isPermanent?"Yes":"No")),console.log(r("Created",new Date(e.createdAt).toLocaleDateString("en-US"))),e.unlocksAt&&console.log(r("Unlocks",new Date(e.unlocksAt).toLocaleDateString("en-US"))),e.duration){let s=Math.round(parseInt(e.duration,10)/604800);console.log(r("Duration",`${s} week(s)`))}console.log()}n.rewards&&console.log(r("Rewards",`${n.rewards.amount} WCT`));let a=parseFloat(o.stakeWeight),i=v(a);if(console.log(r("Base APY",`${i.toFixed(2)}%`)),n.position?.duration){let e=Math.round(parseInt(n.position.duration,10)/604800),s=M(i,e);console.log(r("Your APY",`${s.toFixed(2)}%`))}console.log()}async function ut(t){let n=await U(N(t));console.log(`
22
+ ${r("WCT balance",`${D(n)} WCT`)}
23
+ `)}export{b as CAIP2_CHAIN_ID,z as CHAIN_ID,Q as CLI_METADATA,d as L2_WCT_ADDRESS,c as STAKE_WEIGHT_ADDRESS,S as STAKING_REWARD_DISTRIBUTOR_ADDRESS,ut as balance,L as buildAllowanceCallData,_ as buildApprove,N as buildBalanceOfCallData,R as buildClaim,h as buildCreateLock,W as buildIncreaseLockAmount,tt as buildIncreaseUnlockTime,$ as buildLocksCallData,E as buildUpdateLock,P as buildWithdrawAll,v as calculateAPY,M as calculateWeeklyAPY,ct as claim,O as fetchStakeWeight,f as fetchStaking,u as formatDate,D as formatWCT,rt as stake,lt as status,st as unstake};
22
24
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands.ts","../src/constants.ts","../src/contracts.ts","../src/rpc.ts","../src/api.ts","../src/format.ts"],"sourcesContent":["import { parseUnits } from \"viem\";\nimport type { WalletConnectCLI } from \"@walletconnect/cli-sdk\";\nimport {\n CAIP2_CHAIN_ID,\n STAKE_WEIGHT_ADDRESS,\n ONE_WEEK_IN_SECONDS,\n WCT_DECIMALS,\n} from \"./constants.js\";\nimport {\n buildApprove,\n buildCreateLock,\n buildUpdateLock,\n buildIncreaseLockAmount,\n buildWithdrawAll,\n buildClaim,\n buildBalanceOfCallData,\n buildAllowanceCallData,\n buildLocksCallData,\n type TxData,\n} from \"./contracts.js\";\nimport { readUint256, readLocks, estimateGas, waitForTx } from \"./rpc.js\";\nimport { fetchStaking, fetchStakeWeight } from \"./api.js\";\nimport { formatWCT, formatDate, calculateAPY, calculateWeeklyAPY, label } from \"./format.js\";\n\n// ---- Helpers ---------------------------------------------------------- //\n\nfunction computeUnlockTime(weeks: number): bigint {\n const now = Math.floor(Date.now() / 1000);\n return (BigInt(Math.floor((now + weeks * ONE_WEEK_IN_SECONDS) / ONE_WEEK_IN_SECONDS)) *\n BigInt(ONE_WEEK_IN_SECONDS));\n}\n\nasync function sendTx(\n wallet: WalletConnectCLI,\n from: string,\n tx: TxData,\n): Promise<string> {\n const gas = await estimateGas(from, tx);\n return wallet.request<string>({\n chainId: CAIP2_CHAIN_ID,\n request: {\n method: \"eth_sendTransaction\",\n params: [{ from, to: tx.to, data: tx.data, value: \"0x0\", gas }],\n },\n });\n}\n\n// ---- Commands --------------------------------------------------------- //\n\nexport async function stake(\n wallet: WalletConnectCLI,\n address: string,\n amount: string,\n weeks: number,\n): Promise<void> {\n const amountWei = parseUnits(amount, WCT_DECIMALS);\n const requestedUnlockTime = computeUnlockTime(weeks);\n\n // Read on-chain position to determine the right action\n const lock = await readLocks(buildLocksCallData(address));\n const hasPosition = lock.amount > 0n;\n\n if (hasPosition) {\n console.log(\"\\nExisting staking position:\");\n console.log(label(\"Staked\", `${formatWCT(BigInt(lock.amount))} WCT`));\n console.log(label(\"Unlocks\", formatDate(Number(lock.end))));\n }\n\n // Determine effective unlock time — never shorten an existing lock\n let effectiveUnlockTime = requestedUnlockTime;\n const extendingTime = !hasPosition || requestedUnlockTime > lock.end;\n\n if (hasPosition && requestedUnlockTime <= lock.end) {\n effectiveUnlockTime = lock.end;\n console.log(`\\nRequested unlock (${formatDate(Number(requestedUnlockTime))}) is before existing lock end.`);\n console.log(`Keeping current unlock date: ${formatDate(Number(lock.end))}`);\n }\n\n console.log(`\\nAdding ${amount} WCT${extendingTime ? `, extending lock to ${formatDate(Number(effectiveUnlockTime))}` : \"\"}...`);\n\n // Check allowance and approve if needed\n const allowance = await readUint256(buildAllowanceCallData(address, STAKE_WEIGHT_ADDRESS));\n if (allowance < amountWei) {\n console.log(\"\\nApproving WCT spend...\");\n const approveTxHash = await sendTx(wallet, address, buildApprove(STAKE_WEIGHT_ADDRESS, amountWei));\n console.log(label(\"Approve tx\", approveTxHash));\n console.log(\"Waiting for confirmation...\");\n await waitForTx(approveTxHash);\n }\n\n let txHash: string;\n\n if (!hasPosition) {\n console.log(\"\\nCreating new lock...\");\n txHash = await sendTx(wallet, address, buildCreateLock(amountWei, effectiveUnlockTime));\n } else if (extendingTime) {\n console.log(\"\\nUpdating lock (amount + time)...\");\n txHash = await sendTx(wallet, address, buildUpdateLock(amountWei, effectiveUnlockTime));\n } else {\n console.log(\"\\nIncreasing lock amount...\");\n txHash = await sendTx(wallet, address, buildIncreaseLockAmount(amountWei));\n }\n\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nStake submitted successfully.\");\n}\n\nexport async function unstake(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.position) {\n console.log(\"\\nNo staking position found.\");\n return;\n }\n\n if (staking.position.unlocksAt) {\n const unlocksAt = new Date(staking.position.unlocksAt).getTime() / 1000;\n const now = Math.floor(Date.now() / 1000);\n if (unlocksAt > now) {\n console.log(`\\nLock has not expired yet. Unlocks ${formatDate(unlocksAt)}.`);\n return;\n }\n }\n\n console.log(\"\\nWithdrawing all staked WCT...\");\n const txHash = await sendTx(wallet, address, buildWithdrawAll());\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nUnstake submitted successfully.\");\n}\n\nexport async function claim(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.rewards || staking.rewards.amount === \"0\") {\n console.log(\"\\nNo rewards to claim.\");\n return;\n }\n\n console.log(`\\nClaiming ${staking.rewards.amount} WCT in rewards...`);\n const txHash = await sendTx(wallet, address, buildClaim(address));\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nClaim submitted successfully.\");\n}\n\nexport async function status(address: string): Promise<void> {\n const [staking, stakeWeightRes] = await Promise.all([\n fetchStaking(address),\n fetchStakeWeight(),\n ]);\n\n console.log(`\\nStaking status for ${address}\\n`);\n\n if (!staking.position) {\n console.log(\" No staking position found.\\n\");\n } else {\n const pos = staking.position;\n console.log(label(\"Amount\", `${pos.amount} WCT`));\n console.log(label(\"Permanent\", pos.isPermanent ? \"Yes\" : \"No\"));\n console.log(label(\"Created\", new Date(pos.createdAt).toLocaleDateString(\"en-US\")));\n if (pos.unlocksAt) {\n console.log(label(\"Unlocks\", new Date(pos.unlocksAt).toLocaleDateString(\"en-US\")));\n }\n if (pos.duration) {\n const durationWeeks = Math.round(parseInt(pos.duration, 10) / ONE_WEEK_IN_SECONDS);\n console.log(label(\"Duration\", `${durationWeeks} week(s)`));\n }\n console.log();\n }\n\n if (staking.rewards) {\n console.log(label(\"Rewards\", `${staking.rewards.amount} WCT`));\n }\n\n const stakeWeight = parseFloat(stakeWeightRes.stakeWeight);\n const baseAPY = calculateAPY(stakeWeight);\n console.log(label(\"Base APY\", `${baseAPY.toFixed(2)}%`));\n\n if (staking.position?.duration) {\n const weeks = Math.round(parseInt(staking.position.duration, 10) / ONE_WEEK_IN_SECONDS);\n const weeklyAPY = calculateWeeklyAPY(baseAPY, weeks);\n console.log(label(\"Your APY\", `${weeklyAPY.toFixed(2)}%`));\n }\n\n console.log();\n}\n\nexport async function balance(address: string): Promise<void> {\n const bal = await readUint256(buildBalanceOfCallData(address));\n console.log(`\\n${label(\"WCT balance\", `${formatWCT(bal)} WCT`)}\\n`);\n}\n","/** Optimism chain ID */\nexport const CHAIN_ID = 10;\nexport const CAIP2_CHAIN_ID = \"eip155:10\";\n\n/** Contract addresses on Optimism */\nexport const L2_WCT_ADDRESS = \"0xeF4461891DfB3AC8572cCf7C794664A8DD927945\";\nexport const STAKE_WEIGHT_ADDRESS = \"0x521B4C065Bbdbe3E20B3727340730936912DfA46\";\nexport const STAKING_REWARD_DISTRIBUTOR_ADDRESS = \"0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF\";\n\n/** Public Optimism RPC endpoint */\nexport const OPTIMISM_RPC_URL = \"https://mainnet.optimism.io\";\n\n/** Foundation API */\nexport const FOUNDATION_API_URL = \"https://api.walletconnect.network\";\n\n/** Time constants */\nexport const ONE_WEEK_IN_SECONDS = 604800;\n\n/** WCT token decimals */\nexport const WCT_DECIMALS = 18;\n\n/** APY formula constants (from math.ts) */\nexport const APY_SLOPE = -0.06464;\nexport const APY_INTERCEPT = 12.0808;\nexport const APY_STAKE_WEIGHT_DIVISOR = 1_000_000;\nexport const MAX_LOCK_WEEKS = 104;\n\n/** CLI metadata for WalletConnect pairing */\nexport const CLI_METADATA = {\n name: \"walletconnect-staking\",\n description: \"WalletConnect WCT Staking CLI\",\n url: \"https://walletconnect.com\",\n icons: [],\n};\n","import { encodeFunctionData, parseAbi } from \"viem\";\nimport {\n L2_WCT_ADDRESS,\n STAKE_WEIGHT_ADDRESS,\n STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n} from \"./constants.js\";\n\n// ---- ABI fragments ---------------------------------------------------- //\n\nconst erc20Abi = parseAbi([\n \"function approve(address spender, uint256 value) returns (bool)\",\n \"function balanceOf(address account) view returns (uint256)\",\n \"function allowance(address owner, address spender) view returns (uint256)\",\n]);\n\nconst stakeWeightAbi = parseAbi([\n \"function createLock(uint256 amount, uint256 unlockTime)\",\n \"function updateLock(uint256 amount, uint256 unlockTime)\",\n \"function increaseLockAmount(uint256 amount)\",\n \"function increaseUnlockTime(uint256 newUnlockTime)\",\n \"function withdrawAll()\",\n \"function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)\",\n]);\n\nconst stakingRewardDistributorAbi = parseAbi([\n \"function claim(address user) returns (uint256)\",\n]);\n\n// ---- Transaction builders --------------------------------------------- //\n\nexport interface TxData {\n to: string;\n data: string;\n}\n\nexport function buildApprove(spender: string, amount: bigint): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender as `0x${string}`, amount],\n }),\n };\n}\n\nexport function buildCreateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"createLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildUpdateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"updateLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildIncreaseLockAmount(amount: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseLockAmount\",\n args: [amount],\n }),\n };\n}\n\nexport function buildIncreaseUnlockTime(newUnlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseUnlockTime\",\n args: [newUnlockTime],\n }),\n };\n}\n\nexport function buildWithdrawAll(): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"withdrawAll\",\n }),\n };\n}\n\nexport function buildClaim(user: string): TxData {\n return {\n to: STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n data: encodeFunctionData({\n abi: stakingRewardDistributorAbi,\n functionName: \"claim\",\n args: [user as `0x${string}`],\n }),\n };\n}\n\n// ---- Call data builders (for eth_call) -------------------------------- //\n\nexport function buildBalanceOfCallData(account: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [account as `0x${string}`],\n }),\n };\n}\n\nexport function buildAllowanceCallData(owner: string, spender: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [owner as `0x${string}`, spender as `0x${string}`],\n }),\n };\n}\n\nexport function buildLocksCallData(account: string): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"locks\",\n args: [account as `0x${string}`],\n }),\n };\n}\n","import { decodeAbiParameters } from \"viem\";\nimport { OPTIMISM_RPC_URL } from \"./constants.js\";\nimport type { TxData } from \"./contracts.js\";\n\nlet requestId = 1;\n\nasync function rpcRequest<T = string>(\n method: string,\n params: unknown[],\n rpcUrl: string,\n): Promise<T> {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: requestId++,\n method,\n params,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`RPC request failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as { result?: T; error?: { message: string } };\n\n if (json.error) {\n throw new Error(`RPC error: ${json.error.message}`);\n }\n\n return json.result!;\n}\n\nasync function ethCall(tx: TxData, rpcUrl: string): Promise<string> {\n return rpcRequest(\"eth_call\", [{ to: tx.to, data: tx.data }, \"latest\"], rpcUrl);\n}\n\n/** Read a uint256 from an eth_call result */\nexport async function readUint256(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<bigint> {\n const result = await ethCall(tx, rpcUrl);\n const [value] = decodeAbiParameters([{ type: \"uint256\" }], result as `0x${string}`);\n return value;\n}\n\n/** Estimate gas for a transaction, with a 20% buffer */\nexport async function estimateGas(\n from: string,\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<string> {\n const result = await rpcRequest(\n \"eth_estimateGas\",\n [{ from, to: tx.to, data: tx.data, value: \"0x0\" }, \"latest\"],\n rpcUrl,\n );\n // Add 20% buffer to the estimate\n const estimate = BigInt(result);\n const buffered = estimate + estimate / 5n;\n return `0x${buffered.toString(16)}`;\n}\n\ninterface TxReceipt {\n status: string;\n blockNumber: string;\n transactionHash: string;\n}\n\n/** Wait for a transaction to be confirmed (polls eth_getTransactionReceipt) */\nexport async function waitForTx(\n txHash: string,\n rpcUrl: string = OPTIMISM_RPC_URL,\n { intervalMs = 2000, timeoutMs = 60000 } = {},\n): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const receipt = await rpcRequest<TxReceipt | null>(\n \"eth_getTransactionReceipt\",\n [txHash],\n rpcUrl,\n );\n if (receipt) {\n if (receipt.status === \"0x0\") {\n throw new Error(`Transaction ${txHash} reverted`);\n }\n return;\n }\n } catch (err) {\n // Re-throw revert errors, swallow \"receipt not available yet\"\n if (err instanceof Error && err.message.includes(\"reverted\")) throw err;\n }\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n throw new Error(`Transaction ${txHash} not confirmed within ${timeoutMs / 1000}s`);\n}\n\n/** Read the locks() return: (int128 amount, uint256 end, uint256 transferredAmount) */\nexport async function readLocks(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<{ amount: bigint; end: bigint; transferredAmount: bigint }> {\n const result = await ethCall(tx, rpcUrl);\n const [amount, end, transferredAmount] = decodeAbiParameters(\n [{ type: \"int128\" }, { type: \"uint256\" }, { type: \"uint256\" }],\n result as `0x${string}`,\n );\n return { amount: BigInt(amount), end, transferredAmount };\n}\n","import { FOUNDATION_API_URL } from \"./constants.js\";\n\nexport interface StakingPosition {\n isPermanent: boolean;\n amount: string;\n createdAt: string;\n unlocksAt?: string;\n duration?: string;\n}\n\nexport interface StakingRewards {\n amount: string;\n}\n\nexport interface StakingResponse {\n position: StakingPosition | null;\n rewards: StakingRewards | null;\n}\n\nexport interface StakeWeightResponse {\n stakeWeight: string;\n}\n\nfunction getBaseUrl(): string {\n return process.env.FOUNDATION_API_URL || FOUNDATION_API_URL;\n}\n\nexport async function fetchStaking(address: string): Promise<StakingResponse> {\n const url = `${getBaseUrl()}/staking?address=${address}`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakingResponse;\n}\n\nexport async function fetchStakeWeight(): Promise<StakeWeightResponse> {\n const url = `${getBaseUrl()}/stake-weight`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakeWeightResponse;\n}\n","import { formatUnits } from \"viem\";\nimport {\n WCT_DECIMALS,\n APY_SLOPE,\n APY_INTERCEPT,\n APY_STAKE_WEIGHT_DIVISOR,\n MAX_LOCK_WEEKS,\n} from \"./constants.js\";\n\n/** Format a bigint WCT amount as a human-readable string with 2 decimals */\nexport function formatWCT(amount: bigint): string {\n const raw = formatUnits(amount, WCT_DECIMALS);\n const num = parseFloat(raw);\n return num.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\n/** Format a unix timestamp as a locale date string */\nexport function formatDate(timestamp: number): string {\n return new Date(timestamp * 1000).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Calculate base APY from total stake weight (from math.ts) */\nexport function calculateAPY(stakeWeight: number): number {\n return Math.max(\n (stakeWeight / APY_STAKE_WEIGHT_DIVISOR) * APY_SLOPE + APY_INTERCEPT,\n 0,\n );\n}\n\n/** Calculate weekly APY adjusted for lock duration */\nexport function calculateWeeklyAPY(baseAPY: number, weeks: number): number {\n return baseAPY * (Math.min(weeks, MAX_LOCK_WEEKS) / 52);\n}\n\n/** Print a labeled key-value pair */\nexport function label(key: string, value: string): string {\n return ` ${key.padEnd(12)} ${value}`;\n}\n"],"mappings":"AAAA,OAAS,cAAAA,OAAkB,OCCpB,IAAMC,EAAW,GACXC,EAAiB,YAGjBC,EAAiB,6CACjBC,EAAuB,6CACvBC,EAAqC,6CAGrCC,EAAmB,8BAGnBC,EAAqB,oCAe3B,IAAMC,EAAe,CAC1B,KAAM,wBACN,YAAa,gCACb,IAAK,4BACL,MAAO,CAAC,CACV,ECjCA,OAAS,sBAAAC,EAAoB,YAAAC,MAAgB,OAS7C,IAAMC,EAAWC,EAAS,CACxB,kEACA,6DACA,2EACF,CAAC,EAEKC,EAAiBD,EAAS,CAC9B,0DACA,0DACA,8CACA,qDACA,yBACA,8FACF,CAAC,EAEKE,EAA8BF,EAAS,CAC3C,gDACF,CAAC,EASM,SAASG,EAAaC,EAAiBC,EAAwB,CACpE,MAAO,CACL,GAAIC,EACJ,KAAMC,EAAmB,CACvB,IAAKR,EACL,aAAc,UACd,KAAM,CAACK,EAA0BC,CAAM,CACzC,CAAC,CACH,CACF,CAEO,SAASG,EAAgBH,EAAgBI,EAA4B,CAC1E,MAAO,CACL,GAAIC,EACJ,KAAMH,EAAmB,CACvB,IAAKN,EACL,aAAc,aACd,KAAM,CAACI,EAAQI,CAAU,CAC3B,CAAC,CACH,CACF,CAEO,SAASE,EAAgBN,EAAgBI,EAA4B,CAC1E,MAAO,CACL,GAAIC,EACJ,KAAMH,EAAmB,CACvB,IAAKN,EACL,aAAc,aACd,KAAM,CAACI,EAAQI,CAAU,CAC3B,CAAC,CACH,CACF,CAEO,SAASG,EAAwBP,EAAwB,CAC9D,MAAO,CACL,GAAIK,EACJ,KAAMH,EAAmB,CACvB,IAAKN,EACL,aAAc,qBACd,KAAM,CAACI,CAAM,CACf,CAAC,CACH,CACF,CAEO,SAASQ,EAAwBC,EAA+B,CACrE,MAAO,CACL,GAAIJ,EACJ,KAAMH,EAAmB,CACvB,IAAKN,EACL,aAAc,qBACd,KAAM,CAACa,CAAa,CACtB,CAAC,CACH,CACF,CAEO,SAASC,GAA2B,CACzC,MAAO,CACL,GAAIL,EACJ,KAAMH,EAAmB,CACvB,IAAKN,EACL,aAAc,aAChB,CAAC,CACH,CACF,CAEO,SAASe,EAAWC,EAAsB,CAC/C,MAAO,CACL,GAAIC,EACJ,KAAMX,EAAmB,CACvB,IAAKL,EACL,aAAc,QACd,KAAM,CAACe,CAAqB,CAC9B,CAAC,CACH,CACF,CAIO,SAASE,EAAuBC,EAAyB,CAC9D,MAAO,CACL,GAAId,EACJ,KAAMC,EAAmB,CACvB,IAAKR,EACL,aAAc,YACd,KAAM,CAACqB,CAAwB,CACjC,CAAC,CACH,CACF,CAEO,SAASC,EAAuBC,EAAelB,EAAyB,CAC7E,MAAO,CACL,GAAIE,EACJ,KAAMC,EAAmB,CACvB,IAAKR,EACL,aAAc,YACd,KAAM,CAACuB,EAAwBlB,CAAwB,CACzD,CAAC,CACH,CACF,CAEO,SAASmB,EAAmBH,EAAyB,CAC1D,MAAO,CACL,GAAIV,EACJ,KAAMH,EAAmB,CACvB,IAAKN,EACL,aAAc,QACd,KAAM,CAACmB,CAAwB,CACjC,CAAC,CACH,CACF,CChJA,OAAS,uBAAAI,MAA2B,OAIpC,IAAIC,EAAY,EAEhB,eAAeC,EACbC,EACAC,EACAC,EACY,CACZ,IAAMC,EAAM,MAAM,MAAMD,EAAQ,CAC9B,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CACnB,QAAS,MACT,GAAIJ,IACJ,OAAAE,EACA,OAAAC,CACF,CAAC,CACH,CAAC,EAED,GAAI,CAACE,EAAI,GACP,MAAM,IAAI,MAAM,uBAAuBA,EAAI,MAAM,IAAIA,EAAI,UAAU,EAAE,EAGvE,IAAMC,EAAQ,MAAMD,EAAI,KAAK,EAE7B,GAAIC,EAAK,MACP,MAAM,IAAI,MAAM,cAAcA,EAAK,MAAM,OAAO,EAAE,EAGpD,OAAOA,EAAK,MACd,CAEA,eAAeC,EAAQC,EAAYJ,EAAiC,CAClE,OAAOH,EAAW,WAAY,CAAC,CAAE,GAAIO,EAAG,GAAI,KAAMA,EAAG,IAAK,EAAG,QAAQ,EAAGJ,CAAM,CAChF,CAGA,eAAsBK,EACpBD,EACAJ,EAAiBM,EACA,CACjB,IAAMC,EAAS,MAAMJ,EAAQC,EAAIJ,CAAM,EACjC,CAACQ,CAAK,EAAIC,EAAoB,CAAC,CAAE,KAAM,SAAU,CAAC,EAAGF,CAAuB,EAClF,OAAOC,CACT,CAGA,eAAsBE,EACpBC,EACAP,EACAJ,EAAiBM,EACA,CACjB,IAAMC,EAAS,MAAMV,EACnB,kBACA,CAAC,CAAE,KAAAc,EAAM,GAAIP,EAAG,GAAI,KAAMA,EAAG,KAAM,MAAO,KAAM,EAAG,QAAQ,EAC3DJ,CACF,EAEMY,EAAW,OAAOL,CAAM,EAE9B,MAAO,MADUK,EAAWA,EAAW,IAClB,SAAS,EAAE,CAAC,EACnC,CASA,eAAsBC,EACpBC,EACAd,EAAiBM,EACjB,CAAE,WAAAS,EAAa,IAAM,UAAAC,EAAY,GAAM,EAAI,CAAC,EAC7B,CACf,IAAMC,EAAQ,KAAK,IAAI,EACvB,KAAO,KAAK,IAAI,EAAIA,EAAQD,GAAW,CACrC,GAAI,CACF,IAAME,EAAU,MAAMrB,EACpB,4BACA,CAACiB,CAAM,EACPd,CACF,EACA,GAAIkB,EAAS,CACX,GAAIA,EAAQ,SAAW,MACrB,MAAM,IAAI,MAAM,eAAeJ,CAAM,WAAW,EAElD,MACF,CACF,OAASK,EAAK,CAEZ,GAAIA,aAAe,OAASA,EAAI,QAAQ,SAAS,UAAU,EAAG,MAAMA,CACtE,CACA,MAAM,IAAI,QAASC,GAAM,WAAWA,EAAGL,CAAU,CAAC,CACpD,CACA,MAAM,IAAI,MAAM,eAAeD,CAAM,yBAAyBE,EAAY,GAAI,GAAG,CACnF,CAGA,eAAsBK,EACpBjB,EACAJ,EAAiBM,EACoD,CACrE,IAAMC,EAAS,MAAMJ,EAAQC,EAAIJ,CAAM,EACjC,CAACsB,EAAQC,EAAKC,CAAiB,EAAIf,EACvC,CAAC,CAAE,KAAM,QAAS,EAAG,CAAE,KAAM,SAAU,EAAG,CAAE,KAAM,SAAU,CAAC,EAC7DF,CACF,EACA,MAAO,CAAE,OAAQ,OAAOe,CAAM,EAAG,IAAAC,EAAK,kBAAAC,CAAkB,CAC1D,CCzFA,SAASC,GAAqB,CAC5B,OAAO,QAAQ,IAAI,oBAAsBC,CAC3C,CAEA,eAAsBC,EAAaC,EAA2C,CAC5E,IAAMC,EAAM,GAAGJ,EAAW,CAAC,oBAAoBG,CAAO,GAChDE,EAAM,MAAM,MAAMD,CAAG,EAC3B,GAAI,CAACC,EAAI,GACP,MAAM,IAAI,MAAM,yBAAyBA,EAAI,MAAM,IAAIA,EAAI,UAAU,EAAE,EAEzE,OAAQ,MAAMA,EAAI,KAAK,CACzB,CAEA,eAAsBC,GAAiD,CACrE,IAAMF,EAAM,GAAGJ,EAAW,CAAC,gBACrBK,EAAM,MAAM,MAAMD,CAAG,EAC3B,GAAI,CAACC,EAAI,GACP,MAAM,IAAI,MAAM,yBAAyBA,EAAI,MAAM,IAAIA,EAAI,UAAU,EAAE,EAEzE,OAAQ,MAAMA,EAAI,KAAK,CACzB,CC3CA,OAAS,eAAAE,OAAmB,OAUrB,SAASC,EAAUC,EAAwB,CAChD,IAAMC,EAAMC,GAAYF,EAAQ,EAAY,EAE5C,OADY,WAAWC,CAAG,EACf,eAAe,QAAS,CACjC,sBAAuB,EACvB,sBAAuB,CACzB,CAAC,CACH,CAGO,SAASE,EAAWC,EAA2B,CACpD,OAAO,IAAI,KAAKA,EAAY,GAAI,EAAE,mBAAmB,QAAS,CAC5D,KAAM,UACN,MAAO,QACP,IAAK,SACP,CAAC,CACH,CAGO,SAASC,EAAaC,EAA6B,CACxD,OAAO,KAAK,IACTA,EAAc,IAA4B,QAAY,QACvD,CACF,CACF,CAGO,SAASC,EAAmBC,EAAiBC,EAAuB,CACzE,OAAOD,GAAW,KAAK,IAAIC,EAAO,GAAc,EAAI,GACtD,CAGO,SAASC,EAAMC,EAAaC,EAAuB,CACxD,MAAO,KAAKD,EAAI,OAAO,EAAE,CAAC,IAAIC,CAAK,EACrC,CLlBA,SAASC,GAAkBC,EAAuB,CAChD,IAAMC,EAAM,KAAK,MAAM,KAAK,IAAI,EAAI,GAAI,EACxC,OAAQ,OAAO,KAAK,OAAOA,EAAMD,EAAQ,QAAuB,MAAmB,CAAC,EAClF,OAAO,MAAmB,CAC9B,CAEA,eAAeE,EACbC,EACAC,EACAC,EACiB,CACjB,IAAMC,EAAM,MAAMC,EAAYH,EAAMC,CAAE,EACtC,OAAOF,EAAO,QAAgB,CAC5B,QAASK,EACT,QAAS,CACP,OAAQ,sBACR,OAAQ,CAAC,CAAE,KAAAJ,EAAM,GAAIC,EAAG,GAAI,KAAMA,EAAG,KAAM,MAAO,MAAO,IAAAC,CAAI,CAAC,CAChE,CACF,CAAC,CACH,CAIA,eAAsBG,GACpBN,EACAO,EACAC,EACAX,EACe,CACf,IAAMY,EAAYC,GAAWF,EAAQ,EAAY,EAC3CG,EAAsBf,GAAkBC,CAAK,EAG7Ce,EAAO,MAAMC,EAAUC,EAAmBP,CAAO,CAAC,EAClDQ,EAAcH,EAAK,OAAS,GAE9BG,IACF,QAAQ,IAAI;AAAA,2BAA8B,EAC1C,QAAQ,IAAIC,EAAM,SAAU,GAAGC,EAAU,OAAOL,EAAK,MAAM,CAAC,CAAC,MAAM,CAAC,EACpE,QAAQ,IAAII,EAAM,UAAWE,EAAW,OAAON,EAAK,GAAG,CAAC,CAAC,CAAC,GAI5D,IAAIO,EAAsBR,EACpBS,EAAgB,CAACL,GAAeJ,EAAsBC,EAAK,IAYjE,GAVIG,GAAeJ,GAAuBC,EAAK,MAC7CO,EAAsBP,EAAK,IAC3B,QAAQ,IAAI;AAAA,oBAAuBM,EAAW,OAAOP,CAAmB,CAAC,CAAC,gCAAgC,EAC1G,QAAQ,IAAI,gCAAgCO,EAAW,OAAON,EAAK,GAAG,CAAC,CAAC,EAAE,GAG5E,QAAQ,IAAI;AAAA,SAAYJ,CAAM,OAAOY,EAAgB,uBAAuBF,EAAW,OAAOC,CAAmB,CAAC,CAAC,GAAK,EAAE,KAAK,EAG7G,MAAME,EAAYC,EAAuBf,EAASgB,CAAoB,CAAC,EACzEd,EAAW,CACzB,QAAQ,IAAI;AAAA,uBAA0B,EACtC,IAAMe,EAAgB,MAAMzB,EAAOC,EAAQO,EAASkB,EAAaF,EAAsBd,CAAS,CAAC,EACjG,QAAQ,IAAIO,EAAM,aAAcQ,CAAa,CAAC,EAC9C,QAAQ,IAAI,6BAA6B,EACzC,MAAME,EAAUF,CAAa,CAC/B,CAEA,IAAIG,EAECZ,EAGMK,GACT,QAAQ,IAAI;AAAA,iCAAoC,EAChDO,EAAS,MAAM5B,EAAOC,EAAQO,EAASqB,EAAgBnB,EAAWU,CAAmB,CAAC,IAEtF,QAAQ,IAAI;AAAA,0BAA6B,EACzCQ,EAAS,MAAM5B,EAAOC,EAAQO,EAASsB,EAAwBpB,CAAS,CAAC,IAPzE,QAAQ,IAAI;AAAA,qBAAwB,EACpCkB,EAAS,MAAM5B,EAAOC,EAAQO,EAASuB,EAAgBrB,EAAWU,CAAmB,CAAC,GASxF,QAAQ,IAAIH,EAAM,UAAWW,CAAM,CAAC,EACpC,QAAQ,IAAI;AAAA,8BAAiC,CAC/C,CAEA,eAAsBI,GACpB/B,EACAO,EACe,CACf,IAAMyB,EAAU,MAAMC,EAAa1B,CAAO,EAE1C,GAAI,CAACyB,EAAQ,SAAU,CACrB,QAAQ,IAAI;AAAA,2BAA8B,EAC1C,MACF,CAEA,GAAIA,EAAQ,SAAS,UAAW,CAC9B,IAAME,EAAY,IAAI,KAAKF,EAAQ,SAAS,SAAS,EAAE,QAAQ,EAAI,IAC7DlC,EAAM,KAAK,MAAM,KAAK,IAAI,EAAI,GAAI,EACxC,GAAIoC,EAAYpC,EAAK,CACnB,QAAQ,IAAI;AAAA,oCAAuCoB,EAAWgB,CAAS,CAAC,GAAG,EAC3E,MACF,CACF,CAEA,QAAQ,IAAI;AAAA,8BAAiC,EAC7C,IAAMP,EAAS,MAAM5B,EAAOC,EAAQO,EAAS4B,EAAiB,CAAC,EAC/D,QAAQ,IAAInB,EAAM,UAAWW,CAAM,CAAC,EACpC,QAAQ,IAAI;AAAA,gCAAmC,CACjD,CAEA,eAAsBS,GACpBpC,EACAO,EACe,CACf,IAAMyB,EAAU,MAAMC,EAAa1B,CAAO,EAE1C,GAAI,CAACyB,EAAQ,SAAWA,EAAQ,QAAQ,SAAW,IAAK,CACtD,QAAQ,IAAI;AAAA,qBAAwB,EACpC,MACF,CAEA,QAAQ,IAAI;AAAA,WAAcA,EAAQ,QAAQ,MAAM,oBAAoB,EACpE,IAAML,EAAS,MAAM5B,EAAOC,EAAQO,EAAS8B,EAAW9B,CAAO,CAAC,EAChE,QAAQ,IAAIS,EAAM,UAAWW,CAAM,CAAC,EACpC,QAAQ,IAAI;AAAA,8BAAiC,CAC/C,CAEA,eAAsBW,GAAO/B,EAAgC,CAC3D,GAAM,CAACyB,EAASO,CAAc,EAAI,MAAM,QAAQ,IAAI,CAClDN,EAAa1B,CAAO,EACpBiC,EAAiB,CACnB,CAAC,EAID,GAFA,QAAQ,IAAI;AAAA,qBAAwBjC,CAAO;AAAA,CAAI,EAE3C,CAACyB,EAAQ,SACX,QAAQ,IAAI;AAAA,CAAgC,MACvC,CACL,IAAMS,EAAMT,EAAQ,SAOpB,GANA,QAAQ,IAAIhB,EAAM,SAAU,GAAGyB,EAAI,MAAM,MAAM,CAAC,EAChD,QAAQ,IAAIzB,EAAM,YAAayB,EAAI,YAAc,MAAQ,IAAI,CAAC,EAC9D,QAAQ,IAAIzB,EAAM,UAAW,IAAI,KAAKyB,EAAI,SAAS,EAAE,mBAAmB,OAAO,CAAC,CAAC,EAC7EA,EAAI,WACN,QAAQ,IAAIzB,EAAM,UAAW,IAAI,KAAKyB,EAAI,SAAS,EAAE,mBAAmB,OAAO,CAAC,CAAC,EAE/EA,EAAI,SAAU,CAChB,IAAMC,EAAgB,KAAK,MAAM,SAASD,EAAI,SAAU,EAAE,EAAI,MAAmB,EACjF,QAAQ,IAAIzB,EAAM,WAAY,GAAG0B,CAAa,UAAU,CAAC,CAC3D,CACA,QAAQ,IAAI,CACd,CAEIV,EAAQ,SACV,QAAQ,IAAIhB,EAAM,UAAW,GAAGgB,EAAQ,QAAQ,MAAM,MAAM,CAAC,EAG/D,IAAMW,EAAc,WAAWJ,EAAe,WAAW,EACnDK,EAAUC,EAAaF,CAAW,EAGxC,GAFA,QAAQ,IAAI3B,EAAM,WAAY,GAAG4B,EAAQ,QAAQ,CAAC,CAAC,GAAG,CAAC,EAEnDZ,EAAQ,UAAU,SAAU,CAC9B,IAAMnC,EAAQ,KAAK,MAAM,SAASmC,EAAQ,SAAS,SAAU,EAAE,EAAI,MAAmB,EAChFc,EAAYC,EAAmBH,EAAS/C,CAAK,EACnD,QAAQ,IAAImB,EAAM,WAAY,GAAG8B,EAAU,QAAQ,CAAC,CAAC,GAAG,CAAC,CAC3D,CAEA,QAAQ,IAAI,CACd,CAEA,eAAsBE,GAAQzC,EAAgC,CAC5D,IAAM0C,EAAM,MAAM5B,EAAY6B,EAAuB3C,CAAO,CAAC,EAC7D,QAAQ,IAAI;AAAA,EAAKS,EAAM,cAAe,GAAGC,EAAUgC,CAAG,CAAC,MAAM,CAAC;AAAA,CAAI,CACpE","names":["parseUnits","CHAIN_ID","CAIP2_CHAIN_ID","L2_WCT_ADDRESS","STAKE_WEIGHT_ADDRESS","STAKING_REWARD_DISTRIBUTOR_ADDRESS","OPTIMISM_RPC_URL","FOUNDATION_API_URL","CLI_METADATA","encodeFunctionData","parseAbi","erc20Abi","parseAbi","stakeWeightAbi","stakingRewardDistributorAbi","buildApprove","spender","amount","L2_WCT_ADDRESS","encodeFunctionData","buildCreateLock","unlockTime","STAKE_WEIGHT_ADDRESS","buildUpdateLock","buildIncreaseLockAmount","buildIncreaseUnlockTime","newUnlockTime","buildWithdrawAll","buildClaim","user","STAKING_REWARD_DISTRIBUTOR_ADDRESS","buildBalanceOfCallData","account","buildAllowanceCallData","owner","buildLocksCallData","decodeAbiParameters","requestId","rpcRequest","method","params","rpcUrl","res","json","ethCall","tx","readUint256","OPTIMISM_RPC_URL","result","value","decodeAbiParameters","estimateGas","from","estimate","waitForTx","txHash","intervalMs","timeoutMs","start","receipt","err","r","readLocks","amount","end","transferredAmount","getBaseUrl","FOUNDATION_API_URL","fetchStaking","address","url","res","fetchStakeWeight","formatUnits","formatWCT","amount","raw","formatUnits","formatDate","timestamp","calculateAPY","stakeWeight","calculateWeeklyAPY","baseAPY","weeks","label","key","value","computeUnlockTime","weeks","now","sendTx","wallet","from","tx","gas","estimateGas","CAIP2_CHAIN_ID","stake","address","amount","amountWei","parseUnits","requestedUnlockTime","lock","readLocks","buildLocksCallData","hasPosition","label","formatWCT","formatDate","effectiveUnlockTime","extendingTime","readUint256","buildAllowanceCallData","STAKE_WEIGHT_ADDRESS","approveTxHash","buildApprove","waitForTx","txHash","buildUpdateLock","buildIncreaseLockAmount","buildCreateLock","unstake","staking","fetchStaking","unlocksAt","buildWithdrawAll","claim","buildClaim","status","stakeWeightRes","fetchStakeWeight","pos","durationWeeks","stakeWeight","baseAPY","calculateAPY","weeklyAPY","calculateWeeklyAPY","balance","bal","buildBalanceOfCallData"]}
1
+ {"version":3,"sources":["../src/commands.ts","../src/constants.ts","../src/contracts.ts","../src/rpc.ts","../src/api.ts","../src/format.ts"],"sourcesContent":["import { parseUnits } from \"viem\";\nimport type { WalletConnectCLI } from \"@walletconnect/cli-sdk\";\nimport {\n CAIP2_CHAIN_ID,\n STAKE_WEIGHT_ADDRESS,\n ONE_WEEK_IN_SECONDS,\n MIN_REMAINING_LOCK_SECONDS,\n WCT_DECIMALS,\n} from \"./constants.js\";\nimport {\n buildApprove,\n buildCreateLock,\n buildUpdateLock,\n buildIncreaseLockAmount,\n buildWithdrawAll,\n buildClaim,\n buildBalanceOfCallData,\n buildAllowanceCallData,\n buildLocksCallData,\n type TxData,\n} from \"./contracts.js\";\nimport { readUint256, readLocks, estimateGas, waitForTx } from \"./rpc.js\";\nimport { fetchStaking, fetchStakeWeight } from \"./api.js\";\nimport { formatWCT, formatDate, calculateAPY, calculateWeeklyAPY, label } from \"./format.js\";\n\n// ---- Helpers ---------------------------------------------------------- //\n\nfunction computeUnlockTime(weeks: number): bigint {\n const now = Math.floor(Date.now() / 1000);\n return (BigInt(Math.floor((now + weeks * ONE_WEEK_IN_SECONDS) / ONE_WEEK_IN_SECONDS)) *\n BigInt(ONE_WEEK_IN_SECONDS));\n}\n\nasync function sendTx(\n wallet: WalletConnectCLI,\n from: string,\n tx: TxData,\n): Promise<string> {\n const gas = await estimateGas(from, tx);\n return wallet.request<string>({\n chainId: CAIP2_CHAIN_ID,\n request: {\n method: \"eth_sendTransaction\",\n params: [{ from, to: tx.to, data: tx.data, value: \"0x0\", gas }],\n },\n });\n}\n\n// ---- Commands --------------------------------------------------------- //\n\nexport async function stake(\n wallet: WalletConnectCLI,\n address: string,\n amount: string,\n weeks: number,\n): Promise<void> {\n const amountWei = parseUnits(amount, WCT_DECIMALS);\n const requestedUnlockTime = computeUnlockTime(weeks);\n\n // Read on-chain position to determine the right action\n const lock = await readLocks(buildLocksCallData(address));\n const hasPosition = lock.amount > 0n;\n\n if (hasPosition) {\n console.log(\"\\nExisting staking position:\");\n console.log(label(\"Staked\", `${formatWCT(BigInt(lock.amount))} WCT`));\n console.log(label(\"Unlocks\", formatDate(Number(lock.end))));\n }\n\n // Determine effective unlock time — never shorten an existing lock\n let effectiveUnlockTime = requestedUnlockTime;\n const extendingTime = !hasPosition || requestedUnlockTime > lock.end;\n\n if (hasPosition && requestedUnlockTime <= lock.end) {\n effectiveUnlockTime = lock.end;\n console.log(`\\nRequested unlock (${formatDate(Number(requestedUnlockTime))}) is before existing lock end.`);\n console.log(`Keeping current unlock date: ${formatDate(Number(lock.end))}`);\n }\n\n console.log(`\\nAdding ${amount} WCT${extendingTime ? `, extending lock to ${formatDate(Number(effectiveUnlockTime))}` : \"\"}...`);\n\n // Check allowance and approve if needed\n const allowance = await readUint256(buildAllowanceCallData(address, STAKE_WEIGHT_ADDRESS));\n if (allowance < amountWei) {\n console.log(\"\\nApproving WCT spend...\");\n const approveTxHash = await sendTx(wallet, address, buildApprove(STAKE_WEIGHT_ADDRESS, amountWei));\n console.log(label(\"Approve tx\", approveTxHash));\n console.log(\"Waiting for confirmation...\");\n await waitForTx(approveTxHash);\n }\n\n let txHash: string;\n\n if (!hasPosition) {\n console.log(\"\\nCreating new lock...\");\n txHash = await sendTx(wallet, address, buildCreateLock(amountWei, effectiveUnlockTime));\n } else if (extendingTime) {\n console.log(\"\\nUpdating lock (amount + time)...\");\n txHash = await sendTx(wallet, address, buildUpdateLock(amountWei, effectiveUnlockTime));\n } else {\n const now = BigInt(Math.floor(Date.now() / 1000));\n const remaining = lock.end - now;\n\n if (remaining < BigInt(MIN_REMAINING_LOCK_SECONDS)) {\n const days = Number(remaining) / 86400;\n console.error(\n `\\nCannot add to position: lock expires in ~${Math.ceil(days)} day(s), ` +\n `which is below the minimum remaining period of 1 week.\\n` +\n `Re-run with a longer --weeks value to extend your lock.`,\n );\n return;\n }\n\n console.log(\"\\nIncreasing lock amount...\");\n txHash = await sendTx(wallet, address, buildIncreaseLockAmount(amountWei));\n }\n\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nStake submitted successfully.\");\n}\n\nexport async function unstake(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.position) {\n console.log(\"\\nNo staking position found.\");\n return;\n }\n\n if (staking.position.unlocksAt) {\n const unlocksAt = new Date(staking.position.unlocksAt).getTime() / 1000;\n const now = Math.floor(Date.now() / 1000);\n if (unlocksAt > now) {\n console.log(`\\nLock has not expired yet. Unlocks ${formatDate(unlocksAt)}.`);\n return;\n }\n }\n\n console.log(\"\\nWithdrawing all staked WCT...\");\n const txHash = await sendTx(wallet, address, buildWithdrawAll());\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nUnstake submitted successfully.\");\n}\n\nexport async function claim(\n wallet: WalletConnectCLI,\n address: string,\n): Promise<void> {\n const staking = await fetchStaking(address);\n\n if (!staking.rewards || staking.rewards.amount === \"0\") {\n console.log(\"\\nNo rewards to claim.\");\n return;\n }\n\n console.log(`\\nClaiming ${staking.rewards.amount} WCT in rewards...`);\n const txHash = await sendTx(wallet, address, buildClaim(address));\n console.log(label(\"Tx hash\", txHash));\n console.log(\"\\nClaim submitted successfully.\");\n}\n\nexport async function status(address: string): Promise<void> {\n const [staking, stakeWeightRes] = await Promise.all([\n fetchStaking(address),\n fetchStakeWeight(),\n ]);\n\n console.log(`\\nStaking status for ${address}\\n`);\n\n if (!staking.position) {\n console.log(\" No staking position found.\\n\");\n } else {\n const pos = staking.position;\n console.log(label(\"Amount\", `${pos.amount} WCT`));\n console.log(label(\"Permanent\", pos.isPermanent ? \"Yes\" : \"No\"));\n console.log(label(\"Created\", new Date(pos.createdAt).toLocaleDateString(\"en-US\")));\n if (pos.unlocksAt) {\n console.log(label(\"Unlocks\", new Date(pos.unlocksAt).toLocaleDateString(\"en-US\")));\n }\n if (pos.duration) {\n const durationWeeks = Math.round(parseInt(pos.duration, 10) / ONE_WEEK_IN_SECONDS);\n console.log(label(\"Duration\", `${durationWeeks} week(s)`));\n }\n console.log();\n }\n\n if (staking.rewards) {\n console.log(label(\"Rewards\", `${staking.rewards.amount} WCT`));\n }\n\n const stakeWeight = parseFloat(stakeWeightRes.stakeWeight);\n const baseAPY = calculateAPY(stakeWeight);\n console.log(label(\"Base APY\", `${baseAPY.toFixed(2)}%`));\n\n if (staking.position?.duration) {\n const weeks = Math.round(parseInt(staking.position.duration, 10) / ONE_WEEK_IN_SECONDS);\n const weeklyAPY = calculateWeeklyAPY(baseAPY, weeks);\n console.log(label(\"Your APY\", `${weeklyAPY.toFixed(2)}%`));\n }\n\n console.log();\n}\n\nexport async function balance(address: string): Promise<void> {\n const bal = await readUint256(buildBalanceOfCallData(address));\n console.log(`\\n${label(\"WCT balance\", `${formatWCT(bal)} WCT`)}\\n`);\n}\n","/** Optimism chain ID */\nexport const CHAIN_ID = 10;\nexport const CAIP2_CHAIN_ID = \"eip155:10\";\n\n/** Contract addresses on Optimism */\nexport const L2_WCT_ADDRESS = \"0xeF4461891DfB3AC8572cCf7C794664A8DD927945\";\nexport const STAKE_WEIGHT_ADDRESS = \"0x521B4C065Bbdbe3E20B3727340730936912DfA46\";\nexport const STAKING_REWARD_DISTRIBUTOR_ADDRESS = \"0xF368F535e329c6d08DFf0d4b2dA961C4e7F3fCAF\";\n\n/** Public Optimism RPC endpoint */\nexport const OPTIMISM_RPC_URL = \"https://mainnet.optimism.io\";\n\n/** Foundation API */\nexport const FOUNDATION_API_URL = \"https://api.walletconnect.network\";\n\n/** Time constants */\nexport const ONE_WEEK_IN_SECONDS = 604800;\n\n/** Minimum remaining lock time required to increase lock amount (1 week) */\nexport const MIN_REMAINING_LOCK_SECONDS = ONE_WEEK_IN_SECONDS;\n\n/** WCT token decimals */\nexport const WCT_DECIMALS = 18;\n\n/** APY formula constants (from math.ts) */\nexport const APY_SLOPE = -0.06464;\nexport const APY_INTERCEPT = 12.0808;\nexport const APY_STAKE_WEIGHT_DIVISOR = 1_000_000;\nexport const MAX_LOCK_WEEKS = 104;\n\n/** CLI metadata for WalletConnect pairing */\nexport const CLI_METADATA = {\n name: \"walletconnect-staking\",\n description: \"WalletConnect WCT Staking CLI\",\n url: \"https://walletconnect.com\",\n icons: [],\n};\n","import { encodeFunctionData, parseAbi } from \"viem\";\nimport {\n L2_WCT_ADDRESS,\n STAKE_WEIGHT_ADDRESS,\n STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n} from \"./constants.js\";\n\n// ---- ABI fragments ---------------------------------------------------- //\n\nconst erc20Abi = parseAbi([\n \"function approve(address spender, uint256 value) returns (bool)\",\n \"function balanceOf(address account) view returns (uint256)\",\n \"function allowance(address owner, address spender) view returns (uint256)\",\n]);\n\nconst stakeWeightAbi = parseAbi([\n \"function createLock(uint256 amount, uint256 unlockTime)\",\n \"function updateLock(uint256 amount, uint256 unlockTime)\",\n \"function increaseLockAmount(uint256 amount)\",\n \"function increaseUnlockTime(uint256 newUnlockTime)\",\n \"function withdrawAll()\",\n \"function locks(address) view returns (int128 amount, uint256 end, uint256 transferredAmount)\",\n]);\n\nconst stakingRewardDistributorAbi = parseAbi([\n \"function claim(address user) returns (uint256)\",\n]);\n\n// ---- Transaction builders --------------------------------------------- //\n\nexport interface TxData {\n to: string;\n data: string;\n}\n\nexport function buildApprove(spender: string, amount: bigint): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender as `0x${string}`, amount],\n }),\n };\n}\n\nexport function buildCreateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"createLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildUpdateLock(amount: bigint, unlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"updateLock\",\n args: [amount, unlockTime],\n }),\n };\n}\n\nexport function buildIncreaseLockAmount(amount: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseLockAmount\",\n args: [amount],\n }),\n };\n}\n\nexport function buildIncreaseUnlockTime(newUnlockTime: bigint): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"increaseUnlockTime\",\n args: [newUnlockTime],\n }),\n };\n}\n\nexport function buildWithdrawAll(): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"withdrawAll\",\n }),\n };\n}\n\nexport function buildClaim(user: string): TxData {\n return {\n to: STAKING_REWARD_DISTRIBUTOR_ADDRESS,\n data: encodeFunctionData({\n abi: stakingRewardDistributorAbi,\n functionName: \"claim\",\n args: [user as `0x${string}`],\n }),\n };\n}\n\n// ---- Call data builders (for eth_call) -------------------------------- //\n\nexport function buildBalanceOfCallData(account: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [account as `0x${string}`],\n }),\n };\n}\n\nexport function buildAllowanceCallData(owner: string, spender: string): TxData {\n return {\n to: L2_WCT_ADDRESS,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [owner as `0x${string}`, spender as `0x${string}`],\n }),\n };\n}\n\nexport function buildLocksCallData(account: string): TxData {\n return {\n to: STAKE_WEIGHT_ADDRESS,\n data: encodeFunctionData({\n abi: stakeWeightAbi,\n functionName: \"locks\",\n args: [account as `0x${string}`],\n }),\n };\n}\n","import { decodeAbiParameters } from \"viem\";\nimport { OPTIMISM_RPC_URL } from \"./constants.js\";\nimport type { TxData } from \"./contracts.js\";\n\nlet requestId = 1;\n\nasync function rpcRequest<T = string>(\n method: string,\n params: unknown[],\n rpcUrl: string,\n): Promise<T> {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: requestId++,\n method,\n params,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`RPC request failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as { result?: T; error?: { message: string } };\n\n if (json.error) {\n throw new Error(`RPC error: ${json.error.message}`);\n }\n\n return json.result!;\n}\n\nasync function ethCall(tx: TxData, rpcUrl: string): Promise<string> {\n return rpcRequest(\"eth_call\", [{ to: tx.to, data: tx.data }, \"latest\"], rpcUrl);\n}\n\n/** Read a uint256 from an eth_call result */\nexport async function readUint256(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<bigint> {\n const result = await ethCall(tx, rpcUrl);\n const [value] = decodeAbiParameters([{ type: \"uint256\" }], result as `0x${string}`);\n return value;\n}\n\n/** Estimate gas for a transaction, with a 20% buffer */\nexport async function estimateGas(\n from: string,\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<string> {\n const result = await rpcRequest(\n \"eth_estimateGas\",\n [{ from, to: tx.to, data: tx.data, value: \"0x0\" }, \"latest\"],\n rpcUrl,\n );\n // Add 20% buffer to the estimate\n const estimate = BigInt(result);\n const buffered = estimate + estimate / 5n;\n return `0x${buffered.toString(16)}`;\n}\n\ninterface TxReceipt {\n status: string;\n blockNumber: string;\n transactionHash: string;\n}\n\n/** Wait for a transaction to be confirmed (polls eth_getTransactionReceipt) */\nexport async function waitForTx(\n txHash: string,\n rpcUrl: string = OPTIMISM_RPC_URL,\n { intervalMs = 2000, timeoutMs = 60000 } = {},\n): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const receipt = await rpcRequest<TxReceipt | null>(\n \"eth_getTransactionReceipt\",\n [txHash],\n rpcUrl,\n );\n if (receipt) {\n if (receipt.status === \"0x0\") {\n throw new Error(`Transaction ${txHash} reverted`);\n }\n return;\n }\n } catch (err) {\n // Re-throw revert errors, swallow \"receipt not available yet\"\n if (err instanceof Error && err.message.includes(\"reverted\")) throw err;\n }\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n throw new Error(`Transaction ${txHash} not confirmed within ${timeoutMs / 1000}s`);\n}\n\n/** Read the locks() return: (int128 amount, uint256 end, uint256 transferredAmount) */\nexport async function readLocks(\n tx: TxData,\n rpcUrl: string = OPTIMISM_RPC_URL,\n): Promise<{ amount: bigint; end: bigint; transferredAmount: bigint }> {\n const result = await ethCall(tx, rpcUrl);\n const [amount, end, transferredAmount] = decodeAbiParameters(\n [{ type: \"int128\" }, { type: \"uint256\" }, { type: \"uint256\" }],\n result as `0x${string}`,\n );\n return { amount: BigInt(amount), end, transferredAmount };\n}\n","import { FOUNDATION_API_URL } from \"./constants.js\";\n\nexport interface StakingPosition {\n isPermanent: boolean;\n amount: string;\n createdAt: string;\n unlocksAt?: string;\n duration?: string;\n}\n\nexport interface StakingRewards {\n amount: string;\n}\n\nexport interface StakingResponse {\n position: StakingPosition | null;\n rewards: StakingRewards | null;\n}\n\nexport interface StakeWeightResponse {\n stakeWeight: string;\n}\n\nfunction getBaseUrl(): string {\n return process.env.FOUNDATION_API_URL || FOUNDATION_API_URL;\n}\n\nexport async function fetchStaking(address: string): Promise<StakingResponse> {\n const url = `${getBaseUrl()}/staking?address=${address}`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakingResponse;\n}\n\nexport async function fetchStakeWeight(): Promise<StakeWeightResponse> {\n const url = `${getBaseUrl()}/stake-weight`;\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Foundation API error: ${res.status} ${res.statusText}`);\n }\n return (await res.json()) as StakeWeightResponse;\n}\n","import { formatUnits } from \"viem\";\nimport {\n WCT_DECIMALS,\n APY_SLOPE,\n APY_INTERCEPT,\n APY_STAKE_WEIGHT_DIVISOR,\n MAX_LOCK_WEEKS,\n} from \"./constants.js\";\n\n/** Format a bigint WCT amount as a human-readable string with 2 decimals */\nexport function formatWCT(amount: bigint): string {\n const raw = formatUnits(amount, WCT_DECIMALS);\n const num = parseFloat(raw);\n return num.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\n/** Format a unix timestamp as a locale date string */\nexport function formatDate(timestamp: number): string {\n return new Date(timestamp * 1000).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Calculate base APY from total stake weight (from math.ts) */\nexport function calculateAPY(stakeWeight: number): number {\n return Math.max(\n (stakeWeight / APY_STAKE_WEIGHT_DIVISOR) * APY_SLOPE + APY_INTERCEPT,\n 0,\n );\n}\n\n/** Calculate weekly APY adjusted for lock duration */\nexport function calculateWeeklyAPY(baseAPY: number, weeks: number): number {\n return baseAPY * (Math.min(weeks, MAX_LOCK_WEEKS) / 52);\n}\n\n/** Print a labeled key-value pair */\nexport function label(key: string, value: string): string {\n return ` ${key.padEnd(12)} ${value}`;\n}\n"],"mappings":"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","names":["parseUnits","CHAIN_ID","CAIP2_CHAIN_ID","L2_WCT_ADDRESS","STAKE_WEIGHT_ADDRESS","STAKING_REWARD_DISTRIBUTOR_ADDRESS","OPTIMISM_RPC_URL","FOUNDATION_API_URL","CLI_METADATA","encodeFunctionData","parseAbi","erc20Abi","parseAbi","stakeWeightAbi","stakingRewardDistributorAbi","buildApprove","spender","amount","L2_WCT_ADDRESS","encodeFunctionData","buildCreateLock","unlockTime","STAKE_WEIGHT_ADDRESS","buildUpdateLock","buildIncreaseLockAmount","buildIncreaseUnlockTime","newUnlockTime","buildWithdrawAll","buildClaim","user","STAKING_REWARD_DISTRIBUTOR_ADDRESS","buildBalanceOfCallData","account","buildAllowanceCallData","owner","buildLocksCallData","decodeAbiParameters","requestId","rpcRequest","method","params","rpcUrl","res","json","ethCall","tx","readUint256","OPTIMISM_RPC_URL","result","value","decodeAbiParameters","estimateGas","from","estimate","waitForTx","txHash","intervalMs","timeoutMs","start","receipt","err","r","readLocks","amount","end","transferredAmount","getBaseUrl","FOUNDATION_API_URL","fetchStaking","address","url","res","fetchStakeWeight","formatUnits","formatWCT","amount","raw","formatUnits","formatDate","timestamp","calculateAPY","stakeWeight","calculateWeeklyAPY","baseAPY","weeks","label","key","value","computeUnlockTime","weeks","now","sendTx","wallet","from","tx","gas","estimateGas","CAIP2_CHAIN_ID","stake","address","amount","amountWei","parseUnits","requestedUnlockTime","lock","readLocks","buildLocksCallData","hasPosition","label","formatWCT","formatDate","effectiveUnlockTime","extendingTime","readUint256","buildAllowanceCallData","STAKE_WEIGHT_ADDRESS","approveTxHash","buildApprove","waitForTx","txHash","buildCreateLock","buildUpdateLock","remaining","days","buildIncreaseLockAmount","unstake","staking","fetchStaking","unlocksAt","buildWithdrawAll","claim","buildClaim","status","stakeWeightRes","fetchStakeWeight","pos","durationWeeks","stakeWeight","baseAPY","calculateAPY","weeklyAPY","calculateWeeklyAPY","balance","bal","buildBalanceOfCallData"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@walletconnect/staking-cli",
3
3
  "description": "WalletConnect WCT staking CLI — stake, unstake, claim rewards from the terminal",
4
- "version": "0.1.0",
4
+ "version": "0.1.2",
5
5
  "private": false,
6
6
  "author": "WalletConnect, Inc. <walletconnect.com>",
7
7
  "license": "SEE LICENSE IN LICENSE.md",
@@ -16,7 +16,9 @@
16
16
  "require": "./dist/index.cjs"
17
17
  }
18
18
  },
19
- "files": ["dist"],
19
+ "files": [
20
+ "dist"
21
+ ],
20
22
  "keywords": [
21
23
  "walletconnect",
22
24
  "wct",