@avalabs/avalanche-module 0.0.15 → 0.0.17
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/.turbo/turbo-build.log +12 -10
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +4 -4
- package/CHANGELOG.md +16 -0
- package/dist/index.cjs +7 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/manifest.json +5 -4
- package/package.json +5 -5
- package/src/module.ts +5 -0
- package/tsconfig.json +7 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @avalabs/avalanche-module@0.0.
|
|
2
|
+
> @avalabs/avalanche-module@0.0.17 build /home/runner/work/vm-modules/vm-modules/packages/avalanche-module
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: ./src/index.ts
|
|
@@ -10,13 +10,15 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mCJS[39m Build start
|
|
12
12
|
[34mESM[39m Build start
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
[
|
|
16
|
-
[32mESM[39m [1mdist/index.js
|
|
17
|
-
[32mESM[39m
|
|
18
|
-
[
|
|
13
|
+
"RawSimplePriceResponseSchema" and "SimplePriceResponseSchema" are imported from external module "@avalabs/vm-module-types" but never used in "dist/index.js".
|
|
14
|
+
"RawSimplePriceResponseSchema" and "SimplePriceResponseSchema" are imported from external module "@avalabs/vm-module-types" but never used in "dist/index.cjs".
|
|
15
|
+
[32mESM[39m [1mdist/index.js [22m[32m8.01 KB[39m
|
|
16
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m38.07 KB[39m
|
|
17
|
+
[32mESM[39m ⚡️ Build success in 2175ms
|
|
18
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m8.61 KB[39m
|
|
19
|
+
[32mCJS[39m [1mdist/index.cjs.map [22m[32m38.07 KB[39m
|
|
20
|
+
[32mCJS[39m ⚡️ Build success in 2195ms
|
|
19
21
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.cts [22m[32m1.
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.
|
|
22
|
+
[32mDTS[39m ⚡️ Build success in 22645ms
|
|
23
|
+
[32mDTS[39m [1mdist/index.d.cts [22m[32m1.24 KB[39m
|
|
24
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.24 KB[39m
|
package/.turbo/turbo-lint.log
CHANGED
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
> @avalabs/avalanche-module@0.0.
|
|
2
|
+
> @avalabs/avalanche-module@0.0.17 test /home/runner/work/vm-modules/vm-modules/packages/avalanche-module
|
|
3
3
|
> jest
|
|
4
4
|
|
|
5
|
-
PASS src/handlers/get-network-fee.test.ts (
|
|
5
|
+
PASS src/handlers/get-network-fee.test.ts (25.672 s)
|
|
6
6
|
get-network-fee
|
|
7
|
-
✓ should return fixed network fees (
|
|
7
|
+
✓ should return fixed network fees (20 ms)
|
|
8
8
|
|
|
9
9
|
Test Suites: 1 passed, 1 total
|
|
10
10
|
Tests: 1 passed, 1 total
|
|
11
11
|
Snapshots: 0 total
|
|
12
|
-
Time:
|
|
12
|
+
Time: 26.024 s
|
|
13
13
|
Ran all test suites.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @avalabs/avalanche-module
|
|
2
2
|
|
|
3
|
+
## 0.0.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [3590edf]
|
|
8
|
+
- @avalabs/vm-module-types@0.0.17
|
|
9
|
+
|
|
10
|
+
## 0.0.16
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- f39ff3a: Fixe internal dependencies
|
|
15
|
+
- 2bb0a1a: add getHashedBlockchainId util to avalanche module
|
|
16
|
+
- Updated dependencies [bc48457]
|
|
17
|
+
- @avalabs/vm-module-types@0.0.16
|
|
18
|
+
|
|
3
19
|
## 0.0.15
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
var vmModuleTypes = require('@avalabs/vm-module-types');
|
|
4
4
|
var rpcErrors = require('@metamask/rpc-errors');
|
|
5
5
|
var glacierSdk = require('@avalabs/glacier-sdk');
|
|
6
|
-
var
|
|
6
|
+
var m = require('big.js');
|
|
7
7
|
var walletsSdk = require('@avalabs/wallets-sdk');
|
|
8
|
+
var pe = require('crypto');
|
|
9
|
+
var utilsSdk = require('@avalabs/utils-sdk');
|
|
8
10
|
|
|
9
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
12
|
|
|
11
|
-
var
|
|
13
|
+
var m__default = /*#__PURE__*/_interopDefault(m);
|
|
14
|
+
var pe__default = /*#__PURE__*/_interopDefault(pe);
|
|
12
15
|
|
|
13
|
-
var
|
|
16
|
+
var Q=Object.defineProperty;var W=(e,t,r)=>t in e?Q(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var h=(e,t,r)=>(W(e,typeof t!="symbol"?t+"":t,r),r),$=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var w=(e,t,r)=>($(e,t,"read from private field"),r?r.call(e):t.get(e)),C=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r);},A=(e,t,r,a)=>($(e,t,"write to private field"),a?a.call(e,r):t.set(e,r),r);var B={name:"Avalanche",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/bundle.js",packageName:"@avalabs/avalanche-module",registry:"https://registry.npmjs.org"}}},provider:{checksum:"",location:{npm:{filePath:"dist/provider.js",packageName:"@avalabs/avalanche-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo","avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG","avax:imji8papUf2EhV3le337w1vgFauqkJg-","avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl"],namespaces:["avax"]},cointype:"9000",permissions:{rpc:{dapps:!0,methods:["avalanche_sendTransaction","avalanche_*"]}},manifestVersion:"0.0"};async function N(){return {baseFee:BigInt(1e6),low:{maxFeePerGas:BigInt(1e6)},medium:{maxFeePerGas:BigInt(1e6)},high:{maxFeePerGas:BigInt(1e6)},isFixedFee:!0}}var L=e=>e.chainInfo.chainName===glacierSdk.PrimaryNetworkChainName.P_CHAIN,H=e=>e.chainInfo.chainName===glacierSdk.PrimaryNetworkChainName.X_CHAIN;function x(e,t,r="tx"){return `${e}/${r}/${t}`}function f({amount:e,decimals:t}){return e===void 0?new m__default.default(0):new m__default.default(e/10**t)}function G({tx:e,address:t,networkToken:r,chainId:a,explorerUrl:s,isTestnet:c}){let o=new Set(e.consumedUtxos.flatMap(n=>n.addresses)||[]),u=new Set(e.emittedUtxos.flatMap(n=>n.addresses)||[]),i=J({tx:e,isTestnet:c,networkToken:r,froms:o}),l=ee({tx:e,isTestnet:c,networkToken:r}),d=t.toLowerCase().startsWith("p-")?t.slice(2):t,p=o.has(d);return {hash:e.txHash,isContractCall:!1,isIncoming:!p,isOutgoing:p,from:[...o.values()].join(","),to:[...u.values()].join(","),isSender:p,timestamp:e.blockTimestamp*1e3,tokens:[{decimal:r.decimals.toString(),name:r.name,symbol:r.symbol,type:vmModuleTypes.TokenType.NATIVE,amount:i.toString()}],gasUsed:l.toString(),explorerLink:x(s??"",e.txHash,"tx"),txType:e.txType,chainId:a.toString()}}function J({tx:e,isTestnet:t,networkToken:r,froms:a}){let s=["ImportTx","ExportTx"].includes(e.txType),c=e.txType==="BaseTx",o=e.emittedUtxos.filter(n=>n.asset.assetId===y(!!t)&&!n.addresses.some(g=>a.has(g))).reduce((n,g)=>n.add(g.asset.amount),new m__default.default(0)),u=e.value.find(n=>n.assetId===y(!!t))?.amount,i=o.gt(new m__default.default(0))?o:u?new m__default.default(u):new m__default.default(0)??new m__default.default(0),l=t?walletsSdk.Avalanche.FujiContext.pBlockchainID:walletsSdk.Avalanche.MainnetContext.pBlockchainID,d=e.emittedUtxos.filter(n=>n.asset.assetId===y(!!t)&&(e.txType==="ImportTx"&&n.consumedOnChainId===l||e.txType==="ExportTx"&&n.consumedOnChainId!==l)).reduce((n,g)=>n.add(g.amount),new m__default.default(0)),p=c?i:s?d:e.amountStaked.length===0?j(e.value,!!t):j(e.amountStaked,!!t);return f({amount:p?.toNumber(),decimals:r.decimals})}function ee({tx:e,isTestnet:t,networkToken:r}){let a=e.amountBurned?.filter(s=>s.assetId===y(!!t)).reduce((s,c)=>s.add(c.amount),new m__default.default(0));return f({amount:a?.toNumber(),decimals:r.decimals})}function j(e,t){return e.filter(r=>r.assetId===y(t)).reduce((r,a)=>r.add(a.amount),new m__default.default(0))}function y(e){return e?walletsSdk.Avalanche.FujiContext.avaxAssetID:walletsSdk.Avalanche.MainnetContext.avaxAssetID}function D({tx:e,address:t,networkToken:r,chainId:a,explorerUrl:s,isTestnet:c}){let o=new Set(e.consumedUtxos.flatMap(n=>n.addresses)||[]),u=new Set(e.emittedUtxos.flatMap(n=>n.addresses)||[]),i=re({tx:e,isTestnet:c,networkToken:r}),l=ne({isTestnet:c,tx:e,totalAmountCreated:i,networkToken:r}),d=t.toLowerCase().startsWith("x-")?t.slice(2):t,p=o.has(d);return {hash:e.txHash,isContractCall:!1,isIncoming:!p,isOutgoing:p,from:[...o.values()].join(","),to:[...u.values()].join(","),isSender:p,timestamp:e.timestamp*1e3,tokens:[{decimal:r.decimals.toString(),name:r.name,symbol:r.symbol,type:vmModuleTypes.TokenType.NATIVE,amount:i.toString()}],gasUsed:l.toString(),explorerLink:x(s??"",e.txHash,"tx"),txType:e.txType,chainId:a.toString()}}function re({tx:e,isTestnet:t,networkToken:r}){let a=["ImportTx","ExportTx"].includes(e.txType),s=t?walletsSdk.Avalanche.FujiContext.xBlockchainID:walletsSdk.Avalanche.MainnetContext.xBlockchainID,c=e.emittedUtxos.filter(i=>i.asset.assetId===E(!!t)&&(e.txType==="ImportTx"&&i.consumedOnChainId===s||e.txType==="ExportTx"&&i.consumedOnChainId!==s)).reduce((i,l)=>i.add(l.asset.amount),new m__default.default(0)),o=e.amountCreated.filter(i=>i.assetId===E(!!t)).reduce((i,l)=>i.add(l.amount),new m__default.default(0));return f({amount:(a?c:o).toNumber(),decimals:r.decimals})}function ne({isTestnet:e,tx:t,totalAmountCreated:r,networkToken:a}){let c=t.amountUnlocked.filter(o=>o.assetId===E(!!e)).reduce((o,u)=>o.add(u.amount),new m__default.default(0)).minus(r);return f({amount:c.toNumber(),decimals:a.decimals})}function E(e){return e?walletsSdk.Avalanche.FujiContext.avaxAssetID:walletsSdk.Avalanche.MainnetContext.avaxAssetID}var X=async({address:e,nextPageToken:t,offset:r,network:a,glacierService:s})=>{let{isTestnet:c,networkToken:o,explorerUrl:u,chainId:i}=a;if(!s.isHealthy())return {transactions:[],nextPageToken:""};let d=await s.listLatestPrimaryNetworkTransactions({addresses:e,blockchainId:se(e),network:c?glacierSdk.Network.FUJI:glacierSdk.Network.MAINNET,pageSize:r,pageToken:t,sortOrder:glacierSdk.SortOrder.DESC}),p=[];return L(d)&&(p=d.transactions.map(n=>G({tx:n,isTestnet:c,address:e,networkToken:o,explorerUrl:u,chainId:i}))),H(d)&&(p=d.transactions.map(n=>D({tx:n,isTestnet:c,address:e,networkToken:o,explorerUrl:u,chainId:i}))),{transactions:p,nextPageToken:d.nextPageToken}},se=e=>e.split(",")[0]?.toLowerCase().startsWith("p-")?glacierSdk.BlockchainId.P_CHAIN:glacierSdk.BlockchainId.X_CHAIN;var ie={glacierApiUrl:"https://glacier-api.avax.network",proxyApiUrl:"https://proxy-api.avax.network"},oe={glacierApiUrl:"https://glacier-api-dev.avax.network",proxyApiUrl:"https://proxy-api-dev.avax.network"},V=e=>{switch(e){case vmModuleTypes.Environment.PRODUCTION:return ie;case vmModuleTypes.Environment.DEV:return oe}};var b=class extends Error{constructor(){super(...arguments);h(this,"message","Glacier is unhealthy. Try again later.");}},T=class{constructor({glacierApiUrl:t}){h(this,"glacierSdk");h(this,"isGlacierHealthy",!0);h(this,"isHealthy",()=>this.isGlacierHealthy);this.glacierSdk=new glacierSdk.Glacier({BASE:t});}setGlacierToUnhealthy(){this.isGlacierHealthy=!1,setTimeout(()=>{this.isGlacierHealthy=!0;},5*60*1e3);}async listLatestPrimaryNetworkTransactions(t){try{return this.glacierSdk.primaryNetworkTransactions.listLatestPrimaryNetworkTransactions(t)}catch(r){throw r instanceof b&&this.setGlacierToUnhealthy(),r}}};function _({blockchainId:e,isTestnet:t}){let r=t?"fuji"+e:e,a=pe__default.default.createHash("sha256").update(r).digest("base64");return "avax:"+ue(a).substring(0,32)}var ue=e=>e.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");var I="https://api.coingecko.com/api/v3";function K(e=I,t={}){return new utilsSdk.HttpClient(e,t)}function S(e={}){return K(I,e)}S();var P,Z=class{constructor({environment:t}){C(this,P,void 0);let{glacierApiUrl:r}=V(t);A(this,P,new T({glacierApiUrl:r}));}getAddress(){return Promise.resolve("Avalanche address")}getBalances(t){return Promise.resolve({})}getManifest(){let t=vmModuleTypes.parseManifest(B);return t.success?t.data:void 0}getNetworkFee(t){return N()}getTransactionHistory({network:t,address:r,nextPageToken:a,offset:s}){return X({network:t,address:r,nextPageToken:a,offset:s,glacierService:w(this,P)})}getTokens(t){return Promise.resolve([])}async onRpcRequest(t,r){switch(t.method){default:return {error:rpcErrors.rpcErrors.methodNotSupported(`Method ${t.method} not supported`)}}}static getHashedBlockchainId({blockchainId:t,isTestnet:r}){return _({blockchainId:t,isTestnet:r})}};P=new WeakMap;
|
|
14
17
|
|
|
15
|
-
exports.AvalancheModule =
|
|
18
|
+
exports.AvalancheModule = Z;
|
|
16
19
|
//# sourceMappingURL=out.js.map
|
|
17
20
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/module.ts","../manifest.json","../src/handlers/get-network-fee.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/utils.ts","../src/handlers/get-transaction-history/convert-p-chain-transaction.ts","../src/handlers/get-transaction-history/convert-x-chain-transaction.ts","../src/env.ts","../src/services/glacier-service/glacier-service.ts"],"names":["parseManifest","rpcErrors","manifest_default","getNetworkFee","BlockchainId","Network","SortOrder","PrimaryNetworkChainName","Big","isPChainTransactions","value","isXChainTransactions","getExplorerAddressByNetwork","explorerUrl","hash","hashType","getTokenValue","amount","decimals","Avalanche","TokenType","convertPChainTransaction","tx","address","networkToken","chainId","isTestnet","froms","utxo","tos","getAmount","avaxBurnedAmount","getBurnedAmount","chainAddress","isSender","isImportExport","isBaseTx","nonChangeEmittedUtxosAmt","getAvaxAssetId","addr","agg","txValue","val","baseTxValue","pBlockchainId","importExportAmount","nAvaxAmount","aggregateValue","nAvaxFee","accumulator","value_","convertXChainTransaction","xBlockchainId","totalAmountCreated","asset","getTransactionHistory","nextPageToken","offset","network","glacierService","response","getBlockchainIdByAddress","transactions","Environment","prodEnv","devEnv","getEnv","environment","Glacier","GlacierUnhealthyError","__publicField","AvalancheGlacierService","glacierApiUrl","params","error","_glacierService","AvalancheModule","__privateAdd","__privateSet","_","result","__privateGet","request","_network"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetBalancesResponse,\n Environment,\n} from '@avalabs/vm-module-types';\nimport { parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getEnv } from './env';\nimport { AvalancheGlacierService } from './services/glacier-service/glacier-service';\n\nexport class AvalancheModule implements Module {\n #glacierService: AvalancheGlacierService;\n\n constructor({ environment }: { environment: Environment }) {\n const { glacierApiUrl } = getEnv(environment);\n this.#glacierService = new AvalancheGlacierService({ glacierApiUrl });\n }\n\n getAddress(): Promise<string> {\n return Promise.resolve('Avalanche address');\n }\n\n getBalances(_: GetBalancesParams): Promise<GetBalancesResponse> {\n return Promise.resolve({});\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(_: Network): Promise<NetworkFees> {\n return getNetworkFee();\n }\n\n getTransactionHistory({ network, address, nextPageToken, offset }: GetTransactionHistory) {\n return getTransactionHistory({ network, address, nextPageToken, offset, glacierService: this.#glacierService });\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, _network: Network) {\n switch (request.method) {\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n}\n","{\n \"name\": \"Avalanche\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/bundle.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n },\n \"provider\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/provider.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"avax:2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM\",\n \"avax:2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm\",\n \"avax:11111111111111111111111111111111LpoYY\"\n ],\n \"namespaces\": [\"avax\"]\n },\n \"cointype\": \"60\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"avalanche_sendTransaction\", \"avalanche_*\"]\n }\n },\n \"manifestVersion\": \"0.0\"\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\n/**\n * Returns {@link NetworkFees} based on a fixed fee.\n */\nexport async function getNetworkFee(): Promise<NetworkFees> {\n // this is 0.001 Avax denominated in nAvax, taken from https://docs.avax.network/reference/standards/guides/txn-fees#fee-schedule\n return {\n baseFee: BigInt(1000000),\n low: {\n maxFeePerGas: BigInt(1000000),\n },\n medium: {\n maxFeePerGas: BigInt(1000000),\n },\n high: {\n maxFeePerGas: BigInt(1000000),\n },\n isFixedFee: true,\n };\n}\n","import type { GetTransactionHistory, Transaction, TransactionHistoryResponse } from '@avalabs/vm-module-types';\nimport { BlockchainId, Network, SortOrder } from '@avalabs/glacier-sdk';\nimport { isPChainTransactions, isXChainTransactions } from './utils';\nimport { convertPChainTransaction } from './convert-p-chain-transaction';\nimport { convertXChainTransaction } from './convert-x-chain-transaction';\nimport type { AvalancheGlacierService } from '../../services/glacier-service/glacier-service';\n\nexport const getTransactionHistory = async ({\n address,\n nextPageToken,\n offset,\n network,\n glacierService,\n}: GetTransactionHistory & { glacierService: AvalancheGlacierService }): Promise<TransactionHistoryResponse> => {\n const { isTestnet, networkToken, explorerUrl, chainId } = network;\n const isHealthy = glacierService.isHealthy();\n if (!isHealthy) {\n return {\n transactions: [],\n nextPageToken: '',\n };\n }\n\n const response = await glacierService.listLatestPrimaryNetworkTransactions({\n addresses: address,\n blockchainId: getBlockchainIdByAddress(address),\n network: isTestnet ? Network.FUJI : Network.MAINNET,\n pageSize: offset,\n pageToken: nextPageToken,\n sortOrder: SortOrder.DESC,\n });\n\n let transactions: Transaction[] = [];\n if (isPChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertPChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n if (isXChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertXChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n\n return {\n transactions,\n nextPageToken: response.nextPageToken,\n };\n};\n\nconst getBlockchainIdByAddress = (address: string) => {\n // A comma separated list of X-Chain or P-Chain wallet addresses,\n // starting with \"avax\"/\"fuji\", \"P-avax\"/\"P-fuji\" or \"X-avax\"/\"X-fuji\"\n const firstAddress = address.split(',')[0];\n if (firstAddress?.toLowerCase().startsWith('p-')) {\n return BlockchainId.P_CHAIN;\n }\n return BlockchainId.X_CHAIN;\n};\n","import {\n PrimaryNetworkChainName,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n} from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\n\nexport const isPChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListPChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.P_CHAIN;\n};\n\nexport const isXChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListXChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.X_CHAIN;\n};\n\nexport function getExplorerAddressByNetwork(\n explorerUrl: string,\n hash: string,\n hashType: 'address' | 'tx' = 'tx',\n): string {\n return `${explorerUrl}/${hashType}/${hash}`;\n}\n\nexport function getTokenValue({ amount, decimals }: { decimals: number; amount?: number }): Big {\n return amount === undefined ? new Big(0) : new Big(amount / 10 ** decimals);\n}\n","import { type PChainTransaction, type NetworkToken } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertPChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: PChainTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n explorerUrl?: string;\n isTestnet?: boolean;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n });\n\n const avaxBurnedAmount = getBurnedAmount({ tx, isTestnet, networkToken });\n const chainAddress = address.toLowerCase().startsWith('p-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.blockTimestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n froms: Set<string>;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const isBaseTx = tx.txType === 'BaseTx';\n\n const nonChangeEmittedUtxosAmt = tx.emittedUtxos\n .filter(\n (utxo) => utxo.asset.assetId === getAvaxAssetId(!!isTestnet) && !utxo.addresses.some((addr) => froms.has(addr)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n const txValue = tx.value.find((val) => val.assetId === getAvaxAssetId(!!isTestnet))?.amount;\n // This ternary attempts to cover the case where users send themselves AVAX\n // in which case the senders are the recipients and we should use the total tx value.\n const baseTxValue = nonChangeEmittedUtxosAmt.gt(new Big(0))\n ? nonChangeEmittedUtxosAmt\n : txValue\n ? new Big(txValue)\n : new Big(0) ?? new Big(0);\n\n const pBlockchainId = isTestnet ? Avalanche.FujiContext.pBlockchainID : Avalanche.MainnetContext.pBlockchainID;\n\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === pBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== pBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.amount), new Big(0));\n const nAvaxAmount = isBaseTx\n ? baseTxValue\n : isImportExport\n ? importExportAmount\n : tx.amountStaked.length === 0\n ? aggregateValue(tx.value, !!isTestnet)\n : aggregateValue(tx.amountStaked, !!isTestnet);\n return getTokenValue({ amount: nAvaxAmount?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const nAvaxFee = tx.amountBurned\n ?.filter((value) => value.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, value) => accumulator.add(value.amount), new Big(0));\n return getTokenValue({ amount: nAvaxFee?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction aggregateValue(value: PChainTransaction['value'], isTestnet: boolean): Big | undefined {\n return value\n .filter((value_) => value_.assetId === getAvaxAssetId(isTestnet))\n .reduce((accumulator, value_) => accumulator.add(value_.amount), new Big(0));\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { type NetworkToken, XChainNonLinearTransaction, XChainLinearTransaction } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertXChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n isTestnet?: boolean;\n explorerUrl?: string;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n });\n const avaxBurnedAmount = getBurnedAmount({ isTestnet, tx, totalAmountCreated: amount, networkToken });\n const chainAddress = address.toLowerCase().startsWith('x-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.timestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const xBlockchainId = isTestnet ? Avalanche.FujiContext.xBlockchainID : Avalanche.MainnetContext.xBlockchainID;\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === xBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== xBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n\n const totalAmountCreated = tx.amountCreated\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxAmt = isImportExport ? importExportAmount : totalAmountCreated;\n return getTokenValue({ amount: nAvaxAmt.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n isTestnet,\n tx,\n totalAmountCreated,\n networkToken,\n}: {\n isTestnet?: boolean;\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n totalAmountCreated: Big;\n networkToken: NetworkToken;\n}): Big {\n const totalAmountUnlocked = tx.amountUnlocked\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxFee = totalAmountUnlocked.minus(totalAmountCreated);\n return getTokenValue({ amount: nAvaxFee.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import {\n BlockchainId,\n Glacier,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n Network,\n PrimaryNetworkTxType,\n SortOrder,\n} from '@avalabs/glacier-sdk';\n\nclass GlacierUnhealthyError extends Error {\n override message = 'Glacier is unhealthy. Try again later.';\n}\n\nexport class AvalancheGlacierService {\n glacierSdk: Glacier;\n isGlacierHealthy = true;\n\n constructor({ glacierApiUrl }: { glacierApiUrl: string }) {\n this.glacierSdk = new Glacier({ BASE: glacierApiUrl });\n }\n\n isHealthy = (): boolean => this.isGlacierHealthy;\n\n setGlacierToUnhealthy(): void {\n this.isGlacierHealthy = false;\n setTimeout(\n () => {\n this.isGlacierHealthy = true;\n },\n 5 * 60 * 1000,\n ); // 5 minutes\n }\n\n async listLatestPrimaryNetworkTransactions(params: {\n blockchainId: BlockchainId;\n network: Network;\n addresses?: string;\n txTypes?: Array<PrimaryNetworkTxType>;\n startTimestamp?: number;\n endTimestamp?: number;\n pageToken?: string;\n pageSize?: number;\n sortOrder?: SortOrder;\n }): Promise<ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse> {\n try {\n return this.glacierSdk.primaryNetworkTransactions.listLatestPrimaryNetworkTransactions(params);\n } catch (error) {\n if (error instanceof GlacierUnhealthyError) {\n this.setGlacierToUnhealthy();\n }\n throw error;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/module.ts","../manifest.json","../src/handlers/get-network-fee.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/utils.ts","../src/handlers/get-transaction-history/convert-p-chain-transaction.ts","../src/handlers/get-transaction-history/convert-x-chain-transaction.ts","../src/env.ts","../src/services/glacier-service/glacier-service.ts","../../../packages-internal/utils/src/utils/hash-blockchain-id.ts","../../../node_modules/.pnpm/@avalabs+coingecko-sdk@2.8.0-alpha.193_big.js@6.2.1_bn.js@5.2.1_ethers@6.8.1_node-fetch@2.7.0/node_modules/@avalabs/coingecko-sdk/esm/constants.js","../../../node_modules/.pnpm/@avalabs+coingecko-sdk@2.8.0-alpha.193_big.js@6.2.1_bn.js@5.2.1_ethers@6.8.1_node-fetch@2.7.0/node_modules/@avalabs/coingecko-sdk/esm/http.js","../../../packages-internal/utils/src/services/token-service/coingecko-proxy-client.ts","../../../packages-internal/utils/src/services/token-service/token-service.ts"],"names":["parseManifest","rpcErrors","manifest_default","getNetworkFee","BlockchainId","Network","SortOrder","PrimaryNetworkChainName","Big","isPChainTransactions","value","isXChainTransactions","getExplorerAddressByNetwork","explorerUrl","hash","hashType","getTokenValue","amount","decimals","Avalanche","TokenType","convertPChainTransaction","tx","address","networkToken","chainId","isTestnet","froms","utxo","tos","getAmount","avaxBurnedAmount","getBurnedAmount","chainAddress","isSender","isImportExport","isBaseTx","nonChangeEmittedUtxosAmt","getAvaxAssetId","addr","agg","txValue","val","baseTxValue","pBlockchainId","importExportAmount","nAvaxAmount","aggregateValue","nAvaxFee","accumulator","value_","convertXChainTransaction","xBlockchainId","totalAmountCreated","asset","getTransactionHistory","nextPageToken","offset","network","glacierService","response","getBlockchainIdByAddress","transactions","Environment","prodEnv","devEnv","getEnv","environment","Glacier","GlacierUnhealthyError","__publicField","AvalancheGlacierService","glacierApiUrl","params","error","Crypto","hashBlockchainId","blockchainId","blockChainIdWithPrefix","base64","convertBase64ToBase64Url","COINGECKO_URL","DEV_PROXY_API_WORKER_URL","PROXY_API_WORKER_URL","COINGECKO_PROXY_URL","DEV_COINGECKO_PROXY_URL","HttpClient","getCoinGeckoHttp","url","options","getBasicCoingeckoHttp","RawSimplePriceResponseSchema","SimplePriceResponseSchema","coingeckoBasicClient","_glacierService","AvalancheModule","__privateAdd","__privateSet","_","result","__privateGet","request","_network"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetBalancesResponse,\n Environment,\n} from '@avalabs/vm-module-types';\nimport { parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getEnv } from './env';\nimport { AvalancheGlacierService } from './services/glacier-service/glacier-service';\nimport { hashBlockchainId } from '@internal/utils';\n\nexport class AvalancheModule implements Module {\n #glacierService: AvalancheGlacierService;\n\n constructor({ environment }: { environment: Environment }) {\n const { glacierApiUrl } = getEnv(environment);\n this.#glacierService = new AvalancheGlacierService({ glacierApiUrl });\n }\n\n getAddress(): Promise<string> {\n return Promise.resolve('Avalanche address');\n }\n\n getBalances(_: GetBalancesParams): Promise<GetBalancesResponse> {\n return Promise.resolve({});\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(_: Network): Promise<NetworkFees> {\n return getNetworkFee();\n }\n\n getTransactionHistory({ network, address, nextPageToken, offset }: GetTransactionHistory) {\n return getTransactionHistory({ network, address, nextPageToken, offset, glacierService: this.#glacierService });\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, _network: Network) {\n switch (request.method) {\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n\n static getHashedBlockchainId({ blockchainId, isTestnet }: { blockchainId: string; isTestnet?: boolean }): string {\n return hashBlockchainId({ blockchainId, isTestnet });\n }\n}\n","{\n \"name\": \"Avalanche\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/bundle.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n },\n \"provider\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/provider.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo\",\n \"avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG\",\n \"avax:imji8papUf2EhV3le337w1vgFauqkJg-\",\n \"avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl\"\n ],\n \"namespaces\": [\"avax\"]\n },\n \"cointype\": \"9000\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"avalanche_sendTransaction\", \"avalanche_*\"]\n }\n },\n \"manifestVersion\": \"0.0\"\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\n/**\n * Returns {@link NetworkFees} based on a fixed fee.\n */\nexport async function getNetworkFee(): Promise<NetworkFees> {\n // this is 0.001 Avax denominated in nAvax, taken from https://docs.avax.network/reference/standards/guides/txn-fees#fee-schedule\n return {\n baseFee: BigInt(1000000),\n low: {\n maxFeePerGas: BigInt(1000000),\n },\n medium: {\n maxFeePerGas: BigInt(1000000),\n },\n high: {\n maxFeePerGas: BigInt(1000000),\n },\n isFixedFee: true,\n };\n}\n","import type { GetTransactionHistory, Transaction, TransactionHistoryResponse } from '@avalabs/vm-module-types';\nimport { BlockchainId, Network, SortOrder } from '@avalabs/glacier-sdk';\nimport { isPChainTransactions, isXChainTransactions } from './utils';\nimport { convertPChainTransaction } from './convert-p-chain-transaction';\nimport { convertXChainTransaction } from './convert-x-chain-transaction';\nimport type { AvalancheGlacierService } from '../../services/glacier-service/glacier-service';\n\nexport const getTransactionHistory = async ({\n address,\n nextPageToken,\n offset,\n network,\n glacierService,\n}: GetTransactionHistory & { glacierService: AvalancheGlacierService }): Promise<TransactionHistoryResponse> => {\n const { isTestnet, networkToken, explorerUrl, chainId } = network;\n const isHealthy = glacierService.isHealthy();\n if (!isHealthy) {\n return {\n transactions: [],\n nextPageToken: '',\n };\n }\n\n const response = await glacierService.listLatestPrimaryNetworkTransactions({\n addresses: address,\n blockchainId: getBlockchainIdByAddress(address),\n network: isTestnet ? Network.FUJI : Network.MAINNET,\n pageSize: offset,\n pageToken: nextPageToken,\n sortOrder: SortOrder.DESC,\n });\n\n let transactions: Transaction[] = [];\n if (isPChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertPChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n if (isXChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertXChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n\n return {\n transactions,\n nextPageToken: response.nextPageToken,\n };\n};\n\nconst getBlockchainIdByAddress = (address: string) => {\n // A comma separated list of X-Chain or P-Chain wallet addresses,\n // starting with \"avax\"/\"fuji\", \"P-avax\"/\"P-fuji\" or \"X-avax\"/\"X-fuji\"\n const firstAddress = address.split(',')[0];\n if (firstAddress?.toLowerCase().startsWith('p-')) {\n return BlockchainId.P_CHAIN;\n }\n return BlockchainId.X_CHAIN;\n};\n","import {\n PrimaryNetworkChainName,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n} from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\n\nexport const isPChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListPChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.P_CHAIN;\n};\n\nexport const isXChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListXChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.X_CHAIN;\n};\n\nexport function getExplorerAddressByNetwork(\n explorerUrl: string,\n hash: string,\n hashType: 'address' | 'tx' = 'tx',\n): string {\n return `${explorerUrl}/${hashType}/${hash}`;\n}\n\nexport function getTokenValue({ amount, decimals }: { decimals: number; amount?: number }): Big {\n return amount === undefined ? new Big(0) : new Big(amount / 10 ** decimals);\n}\n","import { type PChainTransaction, type NetworkToken } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertPChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: PChainTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n explorerUrl?: string;\n isTestnet?: boolean;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n });\n\n const avaxBurnedAmount = getBurnedAmount({ tx, isTestnet, networkToken });\n const chainAddress = address.toLowerCase().startsWith('p-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.blockTimestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n froms: Set<string>;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const isBaseTx = tx.txType === 'BaseTx';\n\n const nonChangeEmittedUtxosAmt = tx.emittedUtxos\n .filter(\n (utxo) => utxo.asset.assetId === getAvaxAssetId(!!isTestnet) && !utxo.addresses.some((addr) => froms.has(addr)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n const txValue = tx.value.find((val) => val.assetId === getAvaxAssetId(!!isTestnet))?.amount;\n // This ternary attempts to cover the case where users send themselves AVAX\n // in which case the senders are the recipients and we should use the total tx value.\n const baseTxValue = nonChangeEmittedUtxosAmt.gt(new Big(0))\n ? nonChangeEmittedUtxosAmt\n : txValue\n ? new Big(txValue)\n : new Big(0) ?? new Big(0);\n\n const pBlockchainId = isTestnet ? Avalanche.FujiContext.pBlockchainID : Avalanche.MainnetContext.pBlockchainID;\n\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === pBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== pBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.amount), new Big(0));\n const nAvaxAmount = isBaseTx\n ? baseTxValue\n : isImportExport\n ? importExportAmount\n : tx.amountStaked.length === 0\n ? aggregateValue(tx.value, !!isTestnet)\n : aggregateValue(tx.amountStaked, !!isTestnet);\n return getTokenValue({ amount: nAvaxAmount?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const nAvaxFee = tx.amountBurned\n ?.filter((value) => value.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, value) => accumulator.add(value.amount), new Big(0));\n return getTokenValue({ amount: nAvaxFee?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction aggregateValue(value: PChainTransaction['value'], isTestnet: boolean): Big | undefined {\n return value\n .filter((value_) => value_.assetId === getAvaxAssetId(isTestnet))\n .reduce((accumulator, value_) => accumulator.add(value_.amount), new Big(0));\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { type NetworkToken, XChainNonLinearTransaction, XChainLinearTransaction } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertXChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n isTestnet?: boolean;\n explorerUrl?: string;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n });\n const avaxBurnedAmount = getBurnedAmount({ isTestnet, tx, totalAmountCreated: amount, networkToken });\n const chainAddress = address.toLowerCase().startsWith('x-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.timestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const xBlockchainId = isTestnet ? Avalanche.FujiContext.xBlockchainID : Avalanche.MainnetContext.xBlockchainID;\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === xBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== xBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n\n const totalAmountCreated = tx.amountCreated\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxAmt = isImportExport ? importExportAmount : totalAmountCreated;\n return getTokenValue({ amount: nAvaxAmt.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n isTestnet,\n tx,\n totalAmountCreated,\n networkToken,\n}: {\n isTestnet?: boolean;\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n totalAmountCreated: Big;\n networkToken: NetworkToken;\n}): Big {\n const totalAmountUnlocked = tx.amountUnlocked\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxFee = totalAmountUnlocked.minus(totalAmountCreated);\n return getTokenValue({ amount: nAvaxFee.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import {\n BlockchainId,\n Glacier,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n Network,\n PrimaryNetworkTxType,\n SortOrder,\n} from '@avalabs/glacier-sdk';\n\nclass GlacierUnhealthyError extends Error {\n override message = 'Glacier is unhealthy. Try again later.';\n}\n\nexport class AvalancheGlacierService {\n glacierSdk: Glacier;\n isGlacierHealthy = true;\n\n constructor({ glacierApiUrl }: { glacierApiUrl: string }) {\n this.glacierSdk = new Glacier({ BASE: glacierApiUrl });\n }\n\n isHealthy = (): boolean => this.isGlacierHealthy;\n\n setGlacierToUnhealthy(): void {\n this.isGlacierHealthy = false;\n setTimeout(\n () => {\n this.isGlacierHealthy = true;\n },\n 5 * 60 * 1000,\n ); // 5 minutes\n }\n\n async listLatestPrimaryNetworkTransactions(params: {\n blockchainId: BlockchainId;\n network: Network;\n addresses?: string;\n txTypes?: Array<PrimaryNetworkTxType>;\n startTimestamp?: number;\n endTimestamp?: number;\n pageToken?: string;\n pageSize?: number;\n sortOrder?: SortOrder;\n }): Promise<ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse> {\n try {\n return this.glacierSdk.primaryNetworkTransactions.listLatestPrimaryNetworkTransactions(params);\n } catch (error) {\n if (error instanceof GlacierUnhealthyError) {\n this.setGlacierToUnhealthy();\n }\n throw error;\n }\n }\n}\n","import Crypto from 'crypto';\n\n//github.com/gergelylovas/chain-agnostic-namespaces/pull/1/files#diff-cf7185539a48e85d069d194c1c17d7cfa0317b3caa3a89c92e797e3717e49d59R40\nexport function hashBlockchainId({ blockchainId, isTestnet }: { blockchainId: string; isTestnet?: boolean }): string {\n const blockChainIdWithPrefix = isTestnet ? 'fuji' + blockchainId : blockchainId;\n const base64 = Crypto.createHash('sha256').update(blockChainIdWithPrefix).digest('base64');\n const hash = convertBase64ToBase64Url(base64).substring(0, 32);\n return 'avax:' + hash;\n}\n\nconst convertBase64ToBase64Url = (base64: string) => base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n","const COINGECKO_URL = \"https://api.coingecko.com/api/v3\";\nconst COINGECKO_PRO_URL = \"https://pro-api.coingecko.com/api/v3\";\nconst DEV_PROXY_API_WORKER_URL = \"https://proxy-api-dev.avax.network\";\nconst PROXY_API_WORKER_URL = \"https://proxy-api.avax.network\";\nconst COINGECKO_PROXY_URL = `${PROXY_API_WORKER_URL}/proxy/coingecko`;\nconst DEV_COINGECKO_PROXY_URL = `${DEV_PROXY_API_WORKER_URL}/proxy/coingecko`;\n\nexport { COINGECKO_PROXY_URL, COINGECKO_PRO_URL, COINGECKO_URL, DEV_COINGECKO_PROXY_URL, DEV_PROXY_API_WORKER_URL, PROXY_API_WORKER_URL };\n","import { HttpClient } from '@avalabs/utils-sdk';\nimport { COINGECKO_URL, COINGECKO_PROXY_URL, DEV_COINGECKO_PROXY_URL, COINGECKO_PRO_URL } from './constants.js';\n\nfunction getCoinGeckoHttp(url = COINGECKO_URL, options = {}) {\n return new HttpClient(url, options);\n}\nfunction getProxiedCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(COINGECKO_PROXY_URL, { ...options, method: \"POST\" });\n}\nfunction getDevProxiedCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(DEV_COINGECKO_PROXY_URL, {\n ...options,\n method: \"POST\"\n });\n}\nfunction getBasicCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(COINGECKO_URL, options);\n}\nfunction getProCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(COINGECKO_PRO_URL, options);\n}\n\nexport { getBasicCoingeckoHttp, getCoinGeckoHttp, getDevProxiedCoingeckoHttp, getProCoingeckoHttp, getProxiedCoingeckoHttp };\n","import { Zodios } from '@zodios/core';\nimport { RawSimplePriceResponseSchema, SimplePriceResponseSchema } from '@avalabs/vm-module-types';\nimport { boolean, string } from 'zod';\n\nexport const coingeckoProxyClient = (proxyApiUrl: string) =>\n new Zodios(\n `${proxyApiUrl}/proxy/coingecko`,\n [\n {\n method: 'post',\n path: '/simple/price',\n parameters: [\n { name: 'ids', type: 'Query', schema: string() },\n { name: 'vs_currencies', type: 'Query', schema: string() },\n {\n name: 'include_market_cap',\n type: 'Query',\n schema: string().optional(),\n },\n {\n name: 'include_24hr_vol',\n type: 'Query',\n schema: string().optional(),\n },\n {\n name: 'include_24hr_change',\n type: 'Query',\n schema: string().optional(),\n },\n {\n name: 'include_last_updated_at',\n type: 'Query',\n schema: string().optional(),\n },\n ],\n alias: 'simplePrice',\n response: RawSimplePriceResponseSchema,\n },\n {\n method: 'post',\n path: '/simple/token_price/:id',\n parameters: [\n { name: 'id', type: 'Path', schema: string() },\n { name: 'contract_addresses', type: 'Query', schema: string().array() },\n { name: 'vs_currencies', type: 'Query', schema: string().array() },\n {\n name: 'include_market_cap',\n type: 'Query',\n schema: boolean().optional(),\n },\n {\n name: 'include_24hr_vol',\n type: 'Query',\n schema: boolean().optional(),\n },\n {\n name: 'include_24hr_change',\n type: 'Query',\n schema: boolean().optional(),\n },\n ],\n alias: 'simplePriceByContractAddresses',\n response: SimplePriceResponseSchema,\n },\n ],\n {\n axiosConfig: {\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n },\n );\n","import {\n VsCurrencyType,\n getBasicCoingeckoHttp,\n simplePrice,\n simpleTokenPrice,\n type SimplePriceParams,\n} from '@avalabs/coingecko-sdk';\nimport type { Storage, RawSimplePriceResponse, SimplePriceResponse } from '@avalabs/vm-module-types';\nimport { coingeckoRetry } from '../../utils/coingecko-retry';\nimport { arrayHash } from '../../utils/array-hash';\nimport { coingeckoProxyClient } from './coingecko-proxy-client';\n\nconst coingeckoBasicClient = getBasicCoingeckoHttp();\n\nexport class TokenService {\n #storage?: Storage;\n #proxyApiUrl: string;\n\n constructor({ storage, proxyApiUrl }: { proxyApiUrl: string; storage?: Storage }) {\n this.#storage = storage;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n /**\n * Get token price with market data first on coingecko (free tier) directly,\n * if we get 429 error, retry it on coingecko proxy (paid service)\n * @returns token price with market data\n */\n async getSimplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n }: SimplePriceParams): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = coinIds ? `${arrayHash(coinIds)}-${currencies.toString()}` : `${currencies.toString()}`;\n\n const cacheId = `getSimplePrice-${key}`;\n\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data === undefined) {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.simplePrice({\n coinIds,\n currencies,\n marketCap: true,\n vol24: true,\n change24: true,\n useCoingeckoProxy,\n }),\n );\n this.#storage?.set?.(cacheId, data);\n }\n\n return data;\n }\n\n /**\n * Get token price with market data for a list of addresses\n * @param tokenAddresses the token addresses\n * @param assetPlatformId The platform id for all the tokens in the list\n * @param currency the currency to be used\n * @returns a list of token price with market data\n */\n async getPricesByAddresses(\n tokenAddresses: string[],\n assetPlatformId: string,\n currency: VsCurrencyType = VsCurrencyType.USD,\n ): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = `${arrayHash(tokenAddresses)}-${assetPlatformId}-${currency}`;\n\n const cacheId = `getPricesWithMarketDataByAddresses-${key}`;\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data === undefined) {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency,\n useCoingeckoProxy,\n }),\n );\n this.#storage?.set?.(cacheId, data);\n }\n\n return data;\n }\n\n private async fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency = VsCurrencyType.USD,\n useCoingeckoProxy = false,\n }: {\n assetPlatformId: string;\n tokenAddresses: string[];\n currency: VsCurrencyType;\n useCoingeckoProxy?: boolean;\n }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n return coingeckoProxyClient(this.#proxyApiUrl).simplePriceByContractAddresses(undefined, {\n params: {\n id: assetPlatformId,\n },\n queries: {\n contract_addresses: tokenAddresses,\n vs_currencies: [currency],\n include_market_cap: true,\n include_24hr_vol: true,\n include_24hr_change: true,\n },\n });\n }\n\n return simpleTokenPrice(coingeckoBasicClient, {\n assetPlatformId,\n tokenAddresses,\n currencies: [currency],\n marketCap: true,\n vol24: true,\n change24: true,\n });\n }\n\n private async simplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n marketCap = false,\n vol24 = false,\n change24 = false,\n lastUpdated = false,\n useCoingeckoProxy = false,\n }: SimplePriceParams & { useCoingeckoProxy?: boolean }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await coingeckoProxyClient(this.#proxyApiUrl).simplePrice(undefined, {\n queries: {\n ids: coinIds?.join(','),\n vs_currencies: currencies.join(','),\n include_market_cap: String(marketCap),\n include_24hr_vol: String(vol24),\n include_24hr_change: String(change24),\n include_last_updated_at: String(lastUpdated),\n },\n });\n return this.transformSimplePriceResponse(rawData);\n }\n return simplePrice(coingeckoBasicClient, {\n coinIds,\n currencies,\n marketCap,\n vol24,\n change24,\n lastUpdated,\n shouldThrow: true,\n });\n }\n\n private transformSimplePriceResponse = (\n data: RawSimplePriceResponse,\n currencies = [VsCurrencyType.USD],\n ): SimplePriceResponse => {\n const formattedData: SimplePriceResponse = {};\n Object.keys(data).forEach((id) => {\n const tokenData = data[id];\n formattedData[id] = {};\n currencies.forEach((currency: VsCurrencyType) => {\n formattedData[id] = {\n [currency]: {\n price: tokenData?.[currency],\n change24: tokenData?.[`${currency}_24h_change`],\n vol24: tokenData?.[`${currency}_24h_vol`],\n marketCap: tokenData?.[`${currency}_market_cap`],\n },\n };\n });\n });\n return formattedData;\n };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -16,6 +16,10 @@ declare class AvalancheModule implements Module {
|
|
|
16
16
|
onRpcRequest(request: RpcRequest, _network: Network): Promise<{
|
|
17
17
|
error: _metamask_rpc_errors.JsonRpcError<_metamask_rpc_errors.OptionalDataWithOptionalCause>;
|
|
18
18
|
}>;
|
|
19
|
+
static getHashedBlockchainId({ blockchainId, isTestnet }: {
|
|
20
|
+
blockchainId: string;
|
|
21
|
+
isTestnet?: boolean;
|
|
22
|
+
}): string;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
export { AvalancheModule };
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ declare class AvalancheModule implements Module {
|
|
|
16
16
|
onRpcRequest(request: RpcRequest, _network: Network): Promise<{
|
|
17
17
|
error: _metamask_rpc_errors.JsonRpcError<_metamask_rpc_errors.OptionalDataWithOptionalCause>;
|
|
18
18
|
}>;
|
|
19
|
+
static getHashedBlockchainId({ blockchainId, isTestnet }: {
|
|
20
|
+
blockchainId: string;
|
|
21
|
+
isTestnet?: boolean;
|
|
22
|
+
}): string;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
export { AvalancheModule };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { parseManifest, Environment, TokenType } from '@avalabs/vm-module-types';
|
|
2
2
|
import { rpcErrors } from '@metamask/rpc-errors';
|
|
3
3
|
import { Network, SortOrder, BlockchainId, Glacier, PrimaryNetworkChainName } from '@avalabs/glacier-sdk';
|
|
4
|
-
import
|
|
4
|
+
import m from 'big.js';
|
|
5
5
|
import { Avalanche } from '@avalabs/wallets-sdk';
|
|
6
|
+
import pe from 'crypto';
|
|
7
|
+
import { HttpClient } from '@avalabs/utils-sdk';
|
|
6
8
|
|
|
7
|
-
var
|
|
9
|
+
var Q=Object.defineProperty;var W=(e,t,r)=>t in e?Q(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var h=(e,t,r)=>(W(e,typeof t!="symbol"?t+"":t,r),r),$=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var w=(e,t,r)=>($(e,t,"read from private field"),r?r.call(e):t.get(e)),C=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r);},A=(e,t,r,a)=>($(e,t,"write to private field"),a?a.call(e,r):t.set(e,r),r);var B={name:"Avalanche",description:"",version:"0.0.1",sources:{module:{checksum:"",location:{npm:{filePath:"dist/bundle.js",packageName:"@avalabs/avalanche-module",registry:"https://registry.npmjs.org"}}},provider:{checksum:"",location:{npm:{filePath:"dist/provider.js",packageName:"@avalabs/avalanche-module",registry:"https://registry.npmjs.org"}}}},network:{chainIds:["avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo","avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG","avax:imji8papUf2EhV3le337w1vgFauqkJg-","avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl"],namespaces:["avax"]},cointype:"9000",permissions:{rpc:{dapps:!0,methods:["avalanche_sendTransaction","avalanche_*"]}},manifestVersion:"0.0"};async function N(){return {baseFee:BigInt(1e6),low:{maxFeePerGas:BigInt(1e6)},medium:{maxFeePerGas:BigInt(1e6)},high:{maxFeePerGas:BigInt(1e6)},isFixedFee:!0}}var L=e=>e.chainInfo.chainName===PrimaryNetworkChainName.P_CHAIN,H=e=>e.chainInfo.chainName===PrimaryNetworkChainName.X_CHAIN;function x(e,t,r="tx"){return `${e}/${r}/${t}`}function f({amount:e,decimals:t}){return e===void 0?new m(0):new m(e/10**t)}function G({tx:e,address:t,networkToken:r,chainId:a,explorerUrl:s,isTestnet:c}){let o=new Set(e.consumedUtxos.flatMap(n=>n.addresses)||[]),u=new Set(e.emittedUtxos.flatMap(n=>n.addresses)||[]),i=J({tx:e,isTestnet:c,networkToken:r,froms:o}),l=ee({tx:e,isTestnet:c,networkToken:r}),d=t.toLowerCase().startsWith("p-")?t.slice(2):t,p=o.has(d);return {hash:e.txHash,isContractCall:!1,isIncoming:!p,isOutgoing:p,from:[...o.values()].join(","),to:[...u.values()].join(","),isSender:p,timestamp:e.blockTimestamp*1e3,tokens:[{decimal:r.decimals.toString(),name:r.name,symbol:r.symbol,type:TokenType.NATIVE,amount:i.toString()}],gasUsed:l.toString(),explorerLink:x(s??"",e.txHash,"tx"),txType:e.txType,chainId:a.toString()}}function J({tx:e,isTestnet:t,networkToken:r,froms:a}){let s=["ImportTx","ExportTx"].includes(e.txType),c=e.txType==="BaseTx",o=e.emittedUtxos.filter(n=>n.asset.assetId===y(!!t)&&!n.addresses.some(g=>a.has(g))).reduce((n,g)=>n.add(g.asset.amount),new m(0)),u=e.value.find(n=>n.assetId===y(!!t))?.amount,i=o.gt(new m(0))?o:u?new m(u):new m(0)??new m(0),l=t?Avalanche.FujiContext.pBlockchainID:Avalanche.MainnetContext.pBlockchainID,d=e.emittedUtxos.filter(n=>n.asset.assetId===y(!!t)&&(e.txType==="ImportTx"&&n.consumedOnChainId===l||e.txType==="ExportTx"&&n.consumedOnChainId!==l)).reduce((n,g)=>n.add(g.amount),new m(0)),p=c?i:s?d:e.amountStaked.length===0?j(e.value,!!t):j(e.amountStaked,!!t);return f({amount:p?.toNumber(),decimals:r.decimals})}function ee({tx:e,isTestnet:t,networkToken:r}){let a=e.amountBurned?.filter(s=>s.assetId===y(!!t)).reduce((s,c)=>s.add(c.amount),new m(0));return f({amount:a?.toNumber(),decimals:r.decimals})}function j(e,t){return e.filter(r=>r.assetId===y(t)).reduce((r,a)=>r.add(a.amount),new m(0))}function y(e){return e?Avalanche.FujiContext.avaxAssetID:Avalanche.MainnetContext.avaxAssetID}function D({tx:e,address:t,networkToken:r,chainId:a,explorerUrl:s,isTestnet:c}){let o=new Set(e.consumedUtxos.flatMap(n=>n.addresses)||[]),u=new Set(e.emittedUtxos.flatMap(n=>n.addresses)||[]),i=re({tx:e,isTestnet:c,networkToken:r}),l=ne({isTestnet:c,tx:e,totalAmountCreated:i,networkToken:r}),d=t.toLowerCase().startsWith("x-")?t.slice(2):t,p=o.has(d);return {hash:e.txHash,isContractCall:!1,isIncoming:!p,isOutgoing:p,from:[...o.values()].join(","),to:[...u.values()].join(","),isSender:p,timestamp:e.timestamp*1e3,tokens:[{decimal:r.decimals.toString(),name:r.name,symbol:r.symbol,type:TokenType.NATIVE,amount:i.toString()}],gasUsed:l.toString(),explorerLink:x(s??"",e.txHash,"tx"),txType:e.txType,chainId:a.toString()}}function re({tx:e,isTestnet:t,networkToken:r}){let a=["ImportTx","ExportTx"].includes(e.txType),s=t?Avalanche.FujiContext.xBlockchainID:Avalanche.MainnetContext.xBlockchainID,c=e.emittedUtxos.filter(i=>i.asset.assetId===E(!!t)&&(e.txType==="ImportTx"&&i.consumedOnChainId===s||e.txType==="ExportTx"&&i.consumedOnChainId!==s)).reduce((i,l)=>i.add(l.asset.amount),new m(0)),o=e.amountCreated.filter(i=>i.assetId===E(!!t)).reduce((i,l)=>i.add(l.amount),new m(0));return f({amount:(a?c:o).toNumber(),decimals:r.decimals})}function ne({isTestnet:e,tx:t,totalAmountCreated:r,networkToken:a}){let c=t.amountUnlocked.filter(o=>o.assetId===E(!!e)).reduce((o,u)=>o.add(u.amount),new m(0)).minus(r);return f({amount:c.toNumber(),decimals:a.decimals})}function E(e){return e?Avalanche.FujiContext.avaxAssetID:Avalanche.MainnetContext.avaxAssetID}var X=async({address:e,nextPageToken:t,offset:r,network:a,glacierService:s})=>{let{isTestnet:c,networkToken:o,explorerUrl:u,chainId:i}=a;if(!s.isHealthy())return {transactions:[],nextPageToken:""};let d=await s.listLatestPrimaryNetworkTransactions({addresses:e,blockchainId:se(e),network:c?Network.FUJI:Network.MAINNET,pageSize:r,pageToken:t,sortOrder:SortOrder.DESC}),p=[];return L(d)&&(p=d.transactions.map(n=>G({tx:n,isTestnet:c,address:e,networkToken:o,explorerUrl:u,chainId:i}))),H(d)&&(p=d.transactions.map(n=>D({tx:n,isTestnet:c,address:e,networkToken:o,explorerUrl:u,chainId:i}))),{transactions:p,nextPageToken:d.nextPageToken}},se=e=>e.split(",")[0]?.toLowerCase().startsWith("p-")?BlockchainId.P_CHAIN:BlockchainId.X_CHAIN;var ie={glacierApiUrl:"https://glacier-api.avax.network",proxyApiUrl:"https://proxy-api.avax.network"},oe={glacierApiUrl:"https://glacier-api-dev.avax.network",proxyApiUrl:"https://proxy-api-dev.avax.network"},V=e=>{switch(e){case Environment.PRODUCTION:return ie;case Environment.DEV:return oe}};var b=class extends Error{constructor(){super(...arguments);h(this,"message","Glacier is unhealthy. Try again later.");}},T=class{constructor({glacierApiUrl:t}){h(this,"glacierSdk");h(this,"isGlacierHealthy",!0);h(this,"isHealthy",()=>this.isGlacierHealthy);this.glacierSdk=new Glacier({BASE:t});}setGlacierToUnhealthy(){this.isGlacierHealthy=!1,setTimeout(()=>{this.isGlacierHealthy=!0;},5*60*1e3);}async listLatestPrimaryNetworkTransactions(t){try{return this.glacierSdk.primaryNetworkTransactions.listLatestPrimaryNetworkTransactions(t)}catch(r){throw r instanceof b&&this.setGlacierToUnhealthy(),r}}};function _({blockchainId:e,isTestnet:t}){let r=t?"fuji"+e:e,a=pe.createHash("sha256").update(r).digest("base64");return "avax:"+ue(a).substring(0,32)}var ue=e=>e.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");var I="https://api.coingecko.com/api/v3";function K(e=I,t={}){return new HttpClient(e,t)}function S(e={}){return K(I,e)}S();var P,Z=class{constructor({environment:t}){C(this,P,void 0);let{glacierApiUrl:r}=V(t);A(this,P,new T({glacierApiUrl:r}));}getAddress(){return Promise.resolve("Avalanche address")}getBalances(t){return Promise.resolve({})}getManifest(){let t=parseManifest(B);return t.success?t.data:void 0}getNetworkFee(t){return N()}getTransactionHistory({network:t,address:r,nextPageToken:a,offset:s}){return X({network:t,address:r,nextPageToken:a,offset:s,glacierService:w(this,P)})}getTokens(t){return Promise.resolve([])}async onRpcRequest(t,r){switch(t.method){default:return {error:rpcErrors.methodNotSupported(`Method ${t.method} not supported`)}}}static getHashedBlockchainId({blockchainId:t,isTestnet:r}){return _({blockchainId:t,isTestnet:r})}};P=new WeakMap;
|
|
8
10
|
|
|
9
|
-
export {
|
|
11
|
+
export { Z as AvalancheModule };
|
|
10
12
|
//# sourceMappingURL=out.js.map
|
|
11
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/module.ts","../manifest.json","../src/handlers/get-network-fee.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/utils.ts","../src/handlers/get-transaction-history/convert-p-chain-transaction.ts","../src/handlers/get-transaction-history/convert-x-chain-transaction.ts","../src/env.ts","../src/services/glacier-service/glacier-service.ts"],"names":["parseManifest","rpcErrors","manifest_default","getNetworkFee","BlockchainId","Network","SortOrder","PrimaryNetworkChainName","Big","isPChainTransactions","value","isXChainTransactions","getExplorerAddressByNetwork","explorerUrl","hash","hashType","getTokenValue","amount","decimals","Avalanche","TokenType","convertPChainTransaction","tx","address","networkToken","chainId","isTestnet","froms","utxo","tos","getAmount","avaxBurnedAmount","getBurnedAmount","chainAddress","isSender","isImportExport","isBaseTx","nonChangeEmittedUtxosAmt","getAvaxAssetId","addr","agg","txValue","val","baseTxValue","pBlockchainId","importExportAmount","nAvaxAmount","aggregateValue","nAvaxFee","accumulator","value_","convertXChainTransaction","xBlockchainId","totalAmountCreated","asset","getTransactionHistory","nextPageToken","offset","network","glacierService","response","getBlockchainIdByAddress","transactions","Environment","prodEnv","devEnv","getEnv","environment","Glacier","GlacierUnhealthyError","__publicField","AvalancheGlacierService","glacierApiUrl","params","error","_glacierService","AvalancheModule","__privateAdd","__privateSet","_","result","__privateGet","request","_network"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetBalancesResponse,\n Environment,\n} from '@avalabs/vm-module-types';\nimport { parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getEnv } from './env';\nimport { AvalancheGlacierService } from './services/glacier-service/glacier-service';\n\nexport class AvalancheModule implements Module {\n #glacierService: AvalancheGlacierService;\n\n constructor({ environment }: { environment: Environment }) {\n const { glacierApiUrl } = getEnv(environment);\n this.#glacierService = new AvalancheGlacierService({ glacierApiUrl });\n }\n\n getAddress(): Promise<string> {\n return Promise.resolve('Avalanche address');\n }\n\n getBalances(_: GetBalancesParams): Promise<GetBalancesResponse> {\n return Promise.resolve({});\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(_: Network): Promise<NetworkFees> {\n return getNetworkFee();\n }\n\n getTransactionHistory({ network, address, nextPageToken, offset }: GetTransactionHistory) {\n return getTransactionHistory({ network, address, nextPageToken, offset, glacierService: this.#glacierService });\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, _network: Network) {\n switch (request.method) {\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n}\n","{\n \"name\": \"Avalanche\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/bundle.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n },\n \"provider\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/provider.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"avax:2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM\",\n \"avax:2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm\",\n \"avax:11111111111111111111111111111111LpoYY\"\n ],\n \"namespaces\": [\"avax\"]\n },\n \"cointype\": \"60\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"avalanche_sendTransaction\", \"avalanche_*\"]\n }\n },\n \"manifestVersion\": \"0.0\"\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\n/**\n * Returns {@link NetworkFees} based on a fixed fee.\n */\nexport async function getNetworkFee(): Promise<NetworkFees> {\n // this is 0.001 Avax denominated in nAvax, taken from https://docs.avax.network/reference/standards/guides/txn-fees#fee-schedule\n return {\n baseFee: BigInt(1000000),\n low: {\n maxFeePerGas: BigInt(1000000),\n },\n medium: {\n maxFeePerGas: BigInt(1000000),\n },\n high: {\n maxFeePerGas: BigInt(1000000),\n },\n isFixedFee: true,\n };\n}\n","import type { GetTransactionHistory, Transaction, TransactionHistoryResponse } from '@avalabs/vm-module-types';\nimport { BlockchainId, Network, SortOrder } from '@avalabs/glacier-sdk';\nimport { isPChainTransactions, isXChainTransactions } from './utils';\nimport { convertPChainTransaction } from './convert-p-chain-transaction';\nimport { convertXChainTransaction } from './convert-x-chain-transaction';\nimport type { AvalancheGlacierService } from '../../services/glacier-service/glacier-service';\n\nexport const getTransactionHistory = async ({\n address,\n nextPageToken,\n offset,\n network,\n glacierService,\n}: GetTransactionHistory & { glacierService: AvalancheGlacierService }): Promise<TransactionHistoryResponse> => {\n const { isTestnet, networkToken, explorerUrl, chainId } = network;\n const isHealthy = glacierService.isHealthy();\n if (!isHealthy) {\n return {\n transactions: [],\n nextPageToken: '',\n };\n }\n\n const response = await glacierService.listLatestPrimaryNetworkTransactions({\n addresses: address,\n blockchainId: getBlockchainIdByAddress(address),\n network: isTestnet ? Network.FUJI : Network.MAINNET,\n pageSize: offset,\n pageToken: nextPageToken,\n sortOrder: SortOrder.DESC,\n });\n\n let transactions: Transaction[] = [];\n if (isPChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertPChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n if (isXChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertXChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n\n return {\n transactions,\n nextPageToken: response.nextPageToken,\n };\n};\n\nconst getBlockchainIdByAddress = (address: string) => {\n // A comma separated list of X-Chain or P-Chain wallet addresses,\n // starting with \"avax\"/\"fuji\", \"P-avax\"/\"P-fuji\" or \"X-avax\"/\"X-fuji\"\n const firstAddress = address.split(',')[0];\n if (firstAddress?.toLowerCase().startsWith('p-')) {\n return BlockchainId.P_CHAIN;\n }\n return BlockchainId.X_CHAIN;\n};\n","import {\n PrimaryNetworkChainName,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n} from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\n\nexport const isPChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListPChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.P_CHAIN;\n};\n\nexport const isXChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListXChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.X_CHAIN;\n};\n\nexport function getExplorerAddressByNetwork(\n explorerUrl: string,\n hash: string,\n hashType: 'address' | 'tx' = 'tx',\n): string {\n return `${explorerUrl}/${hashType}/${hash}`;\n}\n\nexport function getTokenValue({ amount, decimals }: { decimals: number; amount?: number }): Big {\n return amount === undefined ? new Big(0) : new Big(amount / 10 ** decimals);\n}\n","import { type PChainTransaction, type NetworkToken } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertPChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: PChainTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n explorerUrl?: string;\n isTestnet?: boolean;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n });\n\n const avaxBurnedAmount = getBurnedAmount({ tx, isTestnet, networkToken });\n const chainAddress = address.toLowerCase().startsWith('p-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.blockTimestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n froms: Set<string>;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const isBaseTx = tx.txType === 'BaseTx';\n\n const nonChangeEmittedUtxosAmt = tx.emittedUtxos\n .filter(\n (utxo) => utxo.asset.assetId === getAvaxAssetId(!!isTestnet) && !utxo.addresses.some((addr) => froms.has(addr)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n const txValue = tx.value.find((val) => val.assetId === getAvaxAssetId(!!isTestnet))?.amount;\n // This ternary attempts to cover the case where users send themselves AVAX\n // in which case the senders are the recipients and we should use the total tx value.\n const baseTxValue = nonChangeEmittedUtxosAmt.gt(new Big(0))\n ? nonChangeEmittedUtxosAmt\n : txValue\n ? new Big(txValue)\n : new Big(0) ?? new Big(0);\n\n const pBlockchainId = isTestnet ? Avalanche.FujiContext.pBlockchainID : Avalanche.MainnetContext.pBlockchainID;\n\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === pBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== pBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.amount), new Big(0));\n const nAvaxAmount = isBaseTx\n ? baseTxValue\n : isImportExport\n ? importExportAmount\n : tx.amountStaked.length === 0\n ? aggregateValue(tx.value, !!isTestnet)\n : aggregateValue(tx.amountStaked, !!isTestnet);\n return getTokenValue({ amount: nAvaxAmount?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const nAvaxFee = tx.amountBurned\n ?.filter((value) => value.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, value) => accumulator.add(value.amount), new Big(0));\n return getTokenValue({ amount: nAvaxFee?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction aggregateValue(value: PChainTransaction['value'], isTestnet: boolean): Big | undefined {\n return value\n .filter((value_) => value_.assetId === getAvaxAssetId(isTestnet))\n .reduce((accumulator, value_) => accumulator.add(value_.amount), new Big(0));\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { type NetworkToken, XChainNonLinearTransaction, XChainLinearTransaction } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertXChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n isTestnet?: boolean;\n explorerUrl?: string;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n });\n const avaxBurnedAmount = getBurnedAmount({ isTestnet, tx, totalAmountCreated: amount, networkToken });\n const chainAddress = address.toLowerCase().startsWith('x-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.timestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const xBlockchainId = isTestnet ? Avalanche.FujiContext.xBlockchainID : Avalanche.MainnetContext.xBlockchainID;\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === xBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== xBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n\n const totalAmountCreated = tx.amountCreated\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxAmt = isImportExport ? importExportAmount : totalAmountCreated;\n return getTokenValue({ amount: nAvaxAmt.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n isTestnet,\n tx,\n totalAmountCreated,\n networkToken,\n}: {\n isTestnet?: boolean;\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n totalAmountCreated: Big;\n networkToken: NetworkToken;\n}): Big {\n const totalAmountUnlocked = tx.amountUnlocked\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxFee = totalAmountUnlocked.minus(totalAmountCreated);\n return getTokenValue({ amount: nAvaxFee.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import {\n BlockchainId,\n Glacier,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n Network,\n PrimaryNetworkTxType,\n SortOrder,\n} from '@avalabs/glacier-sdk';\n\nclass GlacierUnhealthyError extends Error {\n override message = 'Glacier is unhealthy. Try again later.';\n}\n\nexport class AvalancheGlacierService {\n glacierSdk: Glacier;\n isGlacierHealthy = true;\n\n constructor({ glacierApiUrl }: { glacierApiUrl: string }) {\n this.glacierSdk = new Glacier({ BASE: glacierApiUrl });\n }\n\n isHealthy = (): boolean => this.isGlacierHealthy;\n\n setGlacierToUnhealthy(): void {\n this.isGlacierHealthy = false;\n setTimeout(\n () => {\n this.isGlacierHealthy = true;\n },\n 5 * 60 * 1000,\n ); // 5 minutes\n }\n\n async listLatestPrimaryNetworkTransactions(params: {\n blockchainId: BlockchainId;\n network: Network;\n addresses?: string;\n txTypes?: Array<PrimaryNetworkTxType>;\n startTimestamp?: number;\n endTimestamp?: number;\n pageToken?: string;\n pageSize?: number;\n sortOrder?: SortOrder;\n }): Promise<ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse> {\n try {\n return this.glacierSdk.primaryNetworkTransactions.listLatestPrimaryNetworkTransactions(params);\n } catch (error) {\n if (error instanceof GlacierUnhealthyError) {\n this.setGlacierToUnhealthy();\n }\n throw error;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/module.ts","../manifest.json","../src/handlers/get-network-fee.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/utils.ts","../src/handlers/get-transaction-history/convert-p-chain-transaction.ts","../src/handlers/get-transaction-history/convert-x-chain-transaction.ts","../src/env.ts","../src/services/glacier-service/glacier-service.ts","../../../packages-internal/utils/src/utils/hash-blockchain-id.ts","../../../node_modules/.pnpm/@avalabs+coingecko-sdk@2.8.0-alpha.193_big.js@6.2.1_bn.js@5.2.1_ethers@6.8.1_node-fetch@2.7.0/node_modules/@avalabs/coingecko-sdk/esm/constants.js","../../../node_modules/.pnpm/@avalabs+coingecko-sdk@2.8.0-alpha.193_big.js@6.2.1_bn.js@5.2.1_ethers@6.8.1_node-fetch@2.7.0/node_modules/@avalabs/coingecko-sdk/esm/http.js","../../../packages-internal/utils/src/services/token-service/coingecko-proxy-client.ts","../../../packages-internal/utils/src/services/token-service/token-service.ts"],"names":["parseManifest","rpcErrors","manifest_default","getNetworkFee","BlockchainId","Network","SortOrder","PrimaryNetworkChainName","Big","isPChainTransactions","value","isXChainTransactions","getExplorerAddressByNetwork","explorerUrl","hash","hashType","getTokenValue","amount","decimals","Avalanche","TokenType","convertPChainTransaction","tx","address","networkToken","chainId","isTestnet","froms","utxo","tos","getAmount","avaxBurnedAmount","getBurnedAmount","chainAddress","isSender","isImportExport","isBaseTx","nonChangeEmittedUtxosAmt","getAvaxAssetId","addr","agg","txValue","val","baseTxValue","pBlockchainId","importExportAmount","nAvaxAmount","aggregateValue","nAvaxFee","accumulator","value_","convertXChainTransaction","xBlockchainId","totalAmountCreated","asset","getTransactionHistory","nextPageToken","offset","network","glacierService","response","getBlockchainIdByAddress","transactions","Environment","prodEnv","devEnv","getEnv","environment","Glacier","GlacierUnhealthyError","__publicField","AvalancheGlacierService","glacierApiUrl","params","error","Crypto","hashBlockchainId","blockchainId","blockChainIdWithPrefix","base64","convertBase64ToBase64Url","COINGECKO_URL","DEV_PROXY_API_WORKER_URL","PROXY_API_WORKER_URL","COINGECKO_PROXY_URL","DEV_COINGECKO_PROXY_URL","HttpClient","getCoinGeckoHttp","url","options","getBasicCoingeckoHttp","RawSimplePriceResponseSchema","SimplePriceResponseSchema","coingeckoBasicClient","_glacierService","AvalancheModule","__privateAdd","__privateSet","_","result","__privateGet","request","_network"],"mappings":"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","sourcesContent":["import type {\n Module,\n Manifest,\n NetworkFees,\n GetTransactionHistory,\n RpcRequest,\n Network,\n GetBalancesParams,\n GetBalancesResponse,\n Environment,\n} from '@avalabs/vm-module-types';\nimport { parseManifest } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport ManifestJson from '../manifest.json';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';\nimport { getEnv } from './env';\nimport { AvalancheGlacierService } from './services/glacier-service/glacier-service';\nimport { hashBlockchainId } from '@internal/utils';\n\nexport class AvalancheModule implements Module {\n #glacierService: AvalancheGlacierService;\n\n constructor({ environment }: { environment: Environment }) {\n const { glacierApiUrl } = getEnv(environment);\n this.#glacierService = new AvalancheGlacierService({ glacierApiUrl });\n }\n\n getAddress(): Promise<string> {\n return Promise.resolve('Avalanche address');\n }\n\n getBalances(_: GetBalancesParams): Promise<GetBalancesResponse> {\n return Promise.resolve({});\n }\n\n getManifest(): Manifest | undefined {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(_: Network): Promise<NetworkFees> {\n return getNetworkFee();\n }\n\n getTransactionHistory({ network, address, nextPageToken, offset }: GetTransactionHistory) {\n return getTransactionHistory({ network, address, nextPageToken, offset, glacierService: this.#glacierService });\n }\n\n getTokens(_: Network) {\n return Promise.resolve([]);\n }\n\n async onRpcRequest(request: RpcRequest, _network: Network) {\n switch (request.method) {\n default:\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n }\n\n static getHashedBlockchainId({ blockchainId, isTestnet }: { blockchainId: string; isTestnet?: boolean }): string {\n return hashBlockchainId({ blockchainId, isTestnet });\n }\n}\n","{\n \"name\": \"Avalanche\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/bundle.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n },\n \"provider\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/provider.js\",\n \"packageName\": \"@avalabs/avalanche-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo\",\n \"avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG\",\n \"avax:imji8papUf2EhV3le337w1vgFauqkJg-\",\n \"avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl\"\n ],\n \"namespaces\": [\"avax\"]\n },\n \"cointype\": \"9000\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"avalanche_sendTransaction\", \"avalanche_*\"]\n }\n },\n \"manifestVersion\": \"0.0\"\n}\n","import type { NetworkFees } from '@avalabs/vm-module-types';\n\n/**\n * Returns {@link NetworkFees} based on a fixed fee.\n */\nexport async function getNetworkFee(): Promise<NetworkFees> {\n // this is 0.001 Avax denominated in nAvax, taken from https://docs.avax.network/reference/standards/guides/txn-fees#fee-schedule\n return {\n baseFee: BigInt(1000000),\n low: {\n maxFeePerGas: BigInt(1000000),\n },\n medium: {\n maxFeePerGas: BigInt(1000000),\n },\n high: {\n maxFeePerGas: BigInt(1000000),\n },\n isFixedFee: true,\n };\n}\n","import type { GetTransactionHistory, Transaction, TransactionHistoryResponse } from '@avalabs/vm-module-types';\nimport { BlockchainId, Network, SortOrder } from '@avalabs/glacier-sdk';\nimport { isPChainTransactions, isXChainTransactions } from './utils';\nimport { convertPChainTransaction } from './convert-p-chain-transaction';\nimport { convertXChainTransaction } from './convert-x-chain-transaction';\nimport type { AvalancheGlacierService } from '../../services/glacier-service/glacier-service';\n\nexport const getTransactionHistory = async ({\n address,\n nextPageToken,\n offset,\n network,\n glacierService,\n}: GetTransactionHistory & { glacierService: AvalancheGlacierService }): Promise<TransactionHistoryResponse> => {\n const { isTestnet, networkToken, explorerUrl, chainId } = network;\n const isHealthy = glacierService.isHealthy();\n if (!isHealthy) {\n return {\n transactions: [],\n nextPageToken: '',\n };\n }\n\n const response = await glacierService.listLatestPrimaryNetworkTransactions({\n addresses: address,\n blockchainId: getBlockchainIdByAddress(address),\n network: isTestnet ? Network.FUJI : Network.MAINNET,\n pageSize: offset,\n pageToken: nextPageToken,\n sortOrder: SortOrder.DESC,\n });\n\n let transactions: Transaction[] = [];\n if (isPChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertPChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n if (isXChainTransactions(response)) {\n transactions = response.transactions.map((value) =>\n convertXChainTransaction({ tx: value, isTestnet, address, networkToken, explorerUrl, chainId }),\n );\n }\n\n return {\n transactions,\n nextPageToken: response.nextPageToken,\n };\n};\n\nconst getBlockchainIdByAddress = (address: string) => {\n // A comma separated list of X-Chain or P-Chain wallet addresses,\n // starting with \"avax\"/\"fuji\", \"P-avax\"/\"P-fuji\" or \"X-avax\"/\"X-fuji\"\n const firstAddress = address.split(',')[0];\n if (firstAddress?.toLowerCase().startsWith('p-')) {\n return BlockchainId.P_CHAIN;\n }\n return BlockchainId.X_CHAIN;\n};\n","import {\n PrimaryNetworkChainName,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n} from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\n\nexport const isPChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListPChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.P_CHAIN;\n};\n\nexport const isXChainTransactions = (\n value: ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse,\n): value is ListXChainTransactionsResponse => {\n return value.chainInfo.chainName === PrimaryNetworkChainName.X_CHAIN;\n};\n\nexport function getExplorerAddressByNetwork(\n explorerUrl: string,\n hash: string,\n hashType: 'address' | 'tx' = 'tx',\n): string {\n return `${explorerUrl}/${hashType}/${hash}`;\n}\n\nexport function getTokenValue({ amount, decimals }: { decimals: number; amount?: number }): Big {\n return amount === undefined ? new Big(0) : new Big(amount / 10 ** decimals);\n}\n","import { type PChainTransaction, type NetworkToken } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertPChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: PChainTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n explorerUrl?: string;\n isTestnet?: boolean;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n });\n\n const avaxBurnedAmount = getBurnedAmount({ tx, isTestnet, networkToken });\n const chainAddress = address.toLowerCase().startsWith('p-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.blockTimestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n froms,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n froms: Set<string>;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const isBaseTx = tx.txType === 'BaseTx';\n\n const nonChangeEmittedUtxosAmt = tx.emittedUtxos\n .filter(\n (utxo) => utxo.asset.assetId === getAvaxAssetId(!!isTestnet) && !utxo.addresses.some((addr) => froms.has(addr)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n const txValue = tx.value.find((val) => val.assetId === getAvaxAssetId(!!isTestnet))?.amount;\n // This ternary attempts to cover the case where users send themselves AVAX\n // in which case the senders are the recipients and we should use the total tx value.\n const baseTxValue = nonChangeEmittedUtxosAmt.gt(new Big(0))\n ? nonChangeEmittedUtxosAmt\n : txValue\n ? new Big(txValue)\n : new Big(0) ?? new Big(0);\n\n const pBlockchainId = isTestnet ? Avalanche.FujiContext.pBlockchainID : Avalanche.MainnetContext.pBlockchainID;\n\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === pBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== pBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.amount), new Big(0));\n const nAvaxAmount = isBaseTx\n ? baseTxValue\n : isImportExport\n ? importExportAmount\n : tx.amountStaked.length === 0\n ? aggregateValue(tx.value, !!isTestnet)\n : aggregateValue(tx.amountStaked, !!isTestnet);\n return getTokenValue({ amount: nAvaxAmount?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: PChainTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const nAvaxFee = tx.amountBurned\n ?.filter((value) => value.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, value) => accumulator.add(value.amount), new Big(0));\n return getTokenValue({ amount: nAvaxFee?.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction aggregateValue(value: PChainTransaction['value'], isTestnet: boolean): Big | undefined {\n return value\n .filter((value_) => value_.assetId === getAvaxAssetId(isTestnet))\n .reduce((accumulator, value_) => accumulator.add(value_.amount), new Big(0));\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { type NetworkToken, XChainNonLinearTransaction, XChainLinearTransaction } from '@avalabs/glacier-sdk';\nimport Big from 'big.js';\nimport { Avalanche } from '@avalabs/wallets-sdk';\nimport { TokenType, type Transaction } from '@avalabs/vm-module-types';\nimport { getExplorerAddressByNetwork, getTokenValue } from './utils';\n\nexport function convertXChainTransaction({\n tx,\n address,\n networkToken,\n chainId,\n explorerUrl,\n isTestnet,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n address: string;\n networkToken: NetworkToken;\n chainId: number;\n isTestnet?: boolean;\n explorerUrl?: string;\n}): Transaction {\n const froms = new Set(tx.consumedUtxos.flatMap((utxo) => utxo.addresses) || []);\n const tos = new Set(tx.emittedUtxos.flatMap((utxo) => utxo.addresses) || []);\n\n const amount = getAmount({\n tx,\n isTestnet,\n networkToken,\n });\n const avaxBurnedAmount = getBurnedAmount({ isTestnet, tx, totalAmountCreated: amount, networkToken });\n const chainAddress = address.toLowerCase().startsWith('x-') ? address.slice(2) : address;\n const isSender = froms.has(chainAddress);\n\n return {\n hash: tx.txHash,\n isContractCall: false,\n isIncoming: !isSender,\n isOutgoing: isSender,\n from: [...froms.values()].join(','),\n to: [...tos.values()].join(','),\n isSender,\n timestamp: tx.timestamp * 1000, // to millis\n tokens: [\n {\n decimal: networkToken.decimals.toString(),\n name: networkToken.name,\n symbol: networkToken.symbol,\n type: TokenType.NATIVE,\n amount: amount.toString(),\n },\n ],\n gasUsed: avaxBurnedAmount.toString(),\n explorerLink: getExplorerAddressByNetwork(explorerUrl ?? '', tx.txHash, 'tx'),\n txType: tx.txType,\n chainId: chainId.toString(),\n };\n}\n\nfunction getAmount({\n tx,\n isTestnet,\n networkToken,\n}: {\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n isTestnet?: boolean;\n networkToken: NetworkToken;\n}): Big {\n const isImportExport = ['ImportTx', 'ExportTx'].includes(tx.txType);\n const xBlockchainId = isTestnet ? Avalanche.FujiContext.xBlockchainID : Avalanche.MainnetContext.xBlockchainID;\n const importExportAmount = tx.emittedUtxos\n .filter(\n (utxo) =>\n utxo.asset.assetId === getAvaxAssetId(!!isTestnet) &&\n ((tx.txType === 'ImportTx' && utxo.consumedOnChainId === xBlockchainId) ||\n (tx.txType === 'ExportTx' && utxo.consumedOnChainId !== xBlockchainId)),\n )\n .reduce((agg, utxo) => agg.add(utxo.asset.amount), new Big(0));\n\n const totalAmountCreated = tx.amountCreated\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxAmt = isImportExport ? importExportAmount : totalAmountCreated;\n return getTokenValue({ amount: nAvaxAmt.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getBurnedAmount({\n isTestnet,\n tx,\n totalAmountCreated,\n networkToken,\n}: {\n isTestnet?: boolean;\n tx: XChainNonLinearTransaction | XChainLinearTransaction;\n totalAmountCreated: Big;\n networkToken: NetworkToken;\n}): Big {\n const totalAmountUnlocked = tx.amountUnlocked\n .filter((asset) => asset.assetId === getAvaxAssetId(!!isTestnet))\n .reduce((accumulator, asset) => accumulator.add(asset.amount), new Big(0));\n const nAvaxFee = totalAmountUnlocked.minus(totalAmountCreated);\n return getTokenValue({ amount: nAvaxFee.toNumber(), decimals: networkToken.decimals });\n}\n\nfunction getAvaxAssetId(isTestnet: boolean): string {\n return isTestnet ? Avalanche.FujiContext.avaxAssetID : Avalanche.MainnetContext.avaxAssetID;\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n glacierApiUrl: string;\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n glacierApiUrl: 'https://glacier-api.avax.network',\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n glacierApiUrl: 'https://glacier-api-dev.avax.network',\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import {\n BlockchainId,\n Glacier,\n type ListCChainAtomicTransactionsResponse,\n type ListPChainTransactionsResponse,\n type ListXChainTransactionsResponse,\n Network,\n PrimaryNetworkTxType,\n SortOrder,\n} from '@avalabs/glacier-sdk';\n\nclass GlacierUnhealthyError extends Error {\n override message = 'Glacier is unhealthy. Try again later.';\n}\n\nexport class AvalancheGlacierService {\n glacierSdk: Glacier;\n isGlacierHealthy = true;\n\n constructor({ glacierApiUrl }: { glacierApiUrl: string }) {\n this.glacierSdk = new Glacier({ BASE: glacierApiUrl });\n }\n\n isHealthy = (): boolean => this.isGlacierHealthy;\n\n setGlacierToUnhealthy(): void {\n this.isGlacierHealthy = false;\n setTimeout(\n () => {\n this.isGlacierHealthy = true;\n },\n 5 * 60 * 1000,\n ); // 5 minutes\n }\n\n async listLatestPrimaryNetworkTransactions(params: {\n blockchainId: BlockchainId;\n network: Network;\n addresses?: string;\n txTypes?: Array<PrimaryNetworkTxType>;\n startTimestamp?: number;\n endTimestamp?: number;\n pageToken?: string;\n pageSize?: number;\n sortOrder?: SortOrder;\n }): Promise<ListPChainTransactionsResponse | ListXChainTransactionsResponse | ListCChainAtomicTransactionsResponse> {\n try {\n return this.glacierSdk.primaryNetworkTransactions.listLatestPrimaryNetworkTransactions(params);\n } catch (error) {\n if (error instanceof GlacierUnhealthyError) {\n this.setGlacierToUnhealthy();\n }\n throw error;\n }\n }\n}\n","import Crypto from 'crypto';\n\n//github.com/gergelylovas/chain-agnostic-namespaces/pull/1/files#diff-cf7185539a48e85d069d194c1c17d7cfa0317b3caa3a89c92e797e3717e49d59R40\nexport function hashBlockchainId({ blockchainId, isTestnet }: { blockchainId: string; isTestnet?: boolean }): string {\n const blockChainIdWithPrefix = isTestnet ? 'fuji' + blockchainId : blockchainId;\n const base64 = Crypto.createHash('sha256').update(blockChainIdWithPrefix).digest('base64');\n const hash = convertBase64ToBase64Url(base64).substring(0, 32);\n return 'avax:' + hash;\n}\n\nconst convertBase64ToBase64Url = (base64: string) => base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n","const COINGECKO_URL = \"https://api.coingecko.com/api/v3\";\nconst COINGECKO_PRO_URL = \"https://pro-api.coingecko.com/api/v3\";\nconst DEV_PROXY_API_WORKER_URL = \"https://proxy-api-dev.avax.network\";\nconst PROXY_API_WORKER_URL = \"https://proxy-api.avax.network\";\nconst COINGECKO_PROXY_URL = `${PROXY_API_WORKER_URL}/proxy/coingecko`;\nconst DEV_COINGECKO_PROXY_URL = `${DEV_PROXY_API_WORKER_URL}/proxy/coingecko`;\n\nexport { COINGECKO_PROXY_URL, COINGECKO_PRO_URL, COINGECKO_URL, DEV_COINGECKO_PROXY_URL, DEV_PROXY_API_WORKER_URL, PROXY_API_WORKER_URL };\n","import { HttpClient } from '@avalabs/utils-sdk';\nimport { COINGECKO_URL, COINGECKO_PROXY_URL, DEV_COINGECKO_PROXY_URL, COINGECKO_PRO_URL } from './constants.js';\n\nfunction getCoinGeckoHttp(url = COINGECKO_URL, options = {}) {\n return new HttpClient(url, options);\n}\nfunction getProxiedCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(COINGECKO_PROXY_URL, { ...options, method: \"POST\" });\n}\nfunction getDevProxiedCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(DEV_COINGECKO_PROXY_URL, {\n ...options,\n method: \"POST\"\n });\n}\nfunction getBasicCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(COINGECKO_URL, options);\n}\nfunction getProCoingeckoHttp(options = {}) {\n return getCoinGeckoHttp(COINGECKO_PRO_URL, options);\n}\n\nexport { getBasicCoingeckoHttp, getCoinGeckoHttp, getDevProxiedCoingeckoHttp, getProCoingeckoHttp, getProxiedCoingeckoHttp };\n","import { Zodios } from '@zodios/core';\nimport { RawSimplePriceResponseSchema, SimplePriceResponseSchema } from '@avalabs/vm-module-types';\nimport { boolean, string } from 'zod';\n\nexport const coingeckoProxyClient = (proxyApiUrl: string) =>\n new Zodios(\n `${proxyApiUrl}/proxy/coingecko`,\n [\n {\n method: 'post',\n path: '/simple/price',\n parameters: [\n { name: 'ids', type: 'Query', schema: string() },\n { name: 'vs_currencies', type: 'Query', schema: string() },\n {\n name: 'include_market_cap',\n type: 'Query',\n schema: string().optional(),\n },\n {\n name: 'include_24hr_vol',\n type: 'Query',\n schema: string().optional(),\n },\n {\n name: 'include_24hr_change',\n type: 'Query',\n schema: string().optional(),\n },\n {\n name: 'include_last_updated_at',\n type: 'Query',\n schema: string().optional(),\n },\n ],\n alias: 'simplePrice',\n response: RawSimplePriceResponseSchema,\n },\n {\n method: 'post',\n path: '/simple/token_price/:id',\n parameters: [\n { name: 'id', type: 'Path', schema: string() },\n { name: 'contract_addresses', type: 'Query', schema: string().array() },\n { name: 'vs_currencies', type: 'Query', schema: string().array() },\n {\n name: 'include_market_cap',\n type: 'Query',\n schema: boolean().optional(),\n },\n {\n name: 'include_24hr_vol',\n type: 'Query',\n schema: boolean().optional(),\n },\n {\n name: 'include_24hr_change',\n type: 'Query',\n schema: boolean().optional(),\n },\n ],\n alias: 'simplePriceByContractAddresses',\n response: SimplePriceResponseSchema,\n },\n ],\n {\n axiosConfig: {\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n },\n );\n","import {\n VsCurrencyType,\n getBasicCoingeckoHttp,\n simplePrice,\n simpleTokenPrice,\n type SimplePriceParams,\n} from '@avalabs/coingecko-sdk';\nimport type { Storage, RawSimplePriceResponse, SimplePriceResponse } from '@avalabs/vm-module-types';\nimport { coingeckoRetry } from '../../utils/coingecko-retry';\nimport { arrayHash } from '../../utils/array-hash';\nimport { coingeckoProxyClient } from './coingecko-proxy-client';\n\nconst coingeckoBasicClient = getBasicCoingeckoHttp();\n\nexport class TokenService {\n #storage?: Storage;\n #proxyApiUrl: string;\n\n constructor({ storage, proxyApiUrl }: { proxyApiUrl: string; storage?: Storage }) {\n this.#storage = storage;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n /**\n * Get token price with market data first on coingecko (free tier) directly,\n * if we get 429 error, retry it on coingecko proxy (paid service)\n * @returns token price with market data\n */\n async getSimplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n }: SimplePriceParams): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = coinIds ? `${arrayHash(coinIds)}-${currencies.toString()}` : `${currencies.toString()}`;\n\n const cacheId = `getSimplePrice-${key}`;\n\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data === undefined) {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.simplePrice({\n coinIds,\n currencies,\n marketCap: true,\n vol24: true,\n change24: true,\n useCoingeckoProxy,\n }),\n );\n this.#storage?.set?.(cacheId, data);\n }\n\n return data;\n }\n\n /**\n * Get token price with market data for a list of addresses\n * @param tokenAddresses the token addresses\n * @param assetPlatformId The platform id for all the tokens in the list\n * @param currency the currency to be used\n * @returns a list of token price with market data\n */\n async getPricesByAddresses(\n tokenAddresses: string[],\n assetPlatformId: string,\n currency: VsCurrencyType = VsCurrencyType.USD,\n ): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = `${arrayHash(tokenAddresses)}-${assetPlatformId}-${currency}`;\n\n const cacheId = `getPricesWithMarketDataByAddresses-${key}`;\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data === undefined) {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency,\n useCoingeckoProxy,\n }),\n );\n this.#storage?.set?.(cacheId, data);\n }\n\n return data;\n }\n\n private async fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency = VsCurrencyType.USD,\n useCoingeckoProxy = false,\n }: {\n assetPlatformId: string;\n tokenAddresses: string[];\n currency: VsCurrencyType;\n useCoingeckoProxy?: boolean;\n }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n return coingeckoProxyClient(this.#proxyApiUrl).simplePriceByContractAddresses(undefined, {\n params: {\n id: assetPlatformId,\n },\n queries: {\n contract_addresses: tokenAddresses,\n vs_currencies: [currency],\n include_market_cap: true,\n include_24hr_vol: true,\n include_24hr_change: true,\n },\n });\n }\n\n return simpleTokenPrice(coingeckoBasicClient, {\n assetPlatformId,\n tokenAddresses,\n currencies: [currency],\n marketCap: true,\n vol24: true,\n change24: true,\n });\n }\n\n private async simplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n marketCap = false,\n vol24 = false,\n change24 = false,\n lastUpdated = false,\n useCoingeckoProxy = false,\n }: SimplePriceParams & { useCoingeckoProxy?: boolean }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await coingeckoProxyClient(this.#proxyApiUrl).simplePrice(undefined, {\n queries: {\n ids: coinIds?.join(','),\n vs_currencies: currencies.join(','),\n include_market_cap: String(marketCap),\n include_24hr_vol: String(vol24),\n include_24hr_change: String(change24),\n include_last_updated_at: String(lastUpdated),\n },\n });\n return this.transformSimplePriceResponse(rawData);\n }\n return simplePrice(coingeckoBasicClient, {\n coinIds,\n currencies,\n marketCap,\n vol24,\n change24,\n lastUpdated,\n shouldThrow: true,\n });\n }\n\n private transformSimplePriceResponse = (\n data: RawSimplePriceResponse,\n currencies = [VsCurrencyType.USD],\n ): SimplePriceResponse => {\n const formattedData: SimplePriceResponse = {};\n Object.keys(data).forEach((id) => {\n const tokenData = data[id];\n formattedData[id] = {};\n currencies.forEach((currency: VsCurrencyType) => {\n formattedData[id] = {\n [currency]: {\n price: tokenData?.[currency],\n change24: tokenData?.[`${currency}_24h_change`],\n vol24: tokenData?.[`${currency}_24h_vol`],\n marketCap: tokenData?.[`${currency}_market_cap`],\n },\n };\n });\n });\n return formattedData;\n };\n}\n"]}
|
package/manifest.json
CHANGED
|
@@ -26,13 +26,14 @@
|
|
|
26
26
|
},
|
|
27
27
|
"network": {
|
|
28
28
|
"chainIds": [
|
|
29
|
-
"avax:
|
|
30
|
-
"avax:
|
|
31
|
-
"avax:
|
|
29
|
+
"avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo",
|
|
30
|
+
"avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG",
|
|
31
|
+
"avax:imji8papUf2EhV3le337w1vgFauqkJg-",
|
|
32
|
+
"avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl"
|
|
32
33
|
],
|
|
33
34
|
"namespaces": ["avax"]
|
|
34
35
|
},
|
|
35
|
-
"cointype": "
|
|
36
|
+
"cointype": "9000",
|
|
36
37
|
"permissions": {
|
|
37
38
|
"rpc": {
|
|
38
39
|
"dapps": true,
|
package/package.json
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avalabs/avalanche-module",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"main": "dist/index.cjs",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@avalabs/vm-module-types": "0.0.
|
|
9
|
+
"@avalabs/vm-module-types": "0.0.17",
|
|
10
10
|
"@metamask/rpc-errors": "6.3.0",
|
|
11
11
|
"@avalabs/utils-sdk": "v2.8.0-alpha.193",
|
|
12
12
|
"@avalabs/etherscan-sdk": "v2.8.0-alpha.193",
|
|
13
13
|
"@avalabs/glacier-sdk": "v2.8.0-alpha.193",
|
|
14
14
|
"@avalabs/wallets-sdk": "v2.8.0-alpha.193",
|
|
15
|
-
"big.js": "6.2.1"
|
|
16
|
-
"@internal/utils": "0.0.3"
|
|
15
|
+
"big.js": "6.2.1"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
18
|
"@types/jest": "29.5.7",
|
|
@@ -21,8 +20,9 @@
|
|
|
21
20
|
"ts-jest": "29.1.1",
|
|
22
21
|
"tsup": "7.2.0",
|
|
23
22
|
"@types/big.js": "6.2.2",
|
|
23
|
+
"@internal/utils": "0.0.3",
|
|
24
24
|
"@internal/tsup-config": "0.0.1",
|
|
25
|
-
"eslint-config-custom": "0.0.
|
|
25
|
+
"eslint-config-custom": "0.0.1"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsup",
|
package/src/module.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { getNetworkFee } from './handlers/get-network-fee';
|
|
|
16
16
|
import { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';
|
|
17
17
|
import { getEnv } from './env';
|
|
18
18
|
import { AvalancheGlacierService } from './services/glacier-service/glacier-service';
|
|
19
|
+
import { hashBlockchainId } from '@internal/utils';
|
|
19
20
|
|
|
20
21
|
export class AvalancheModule implements Module {
|
|
21
22
|
#glacierService: AvalancheGlacierService;
|
|
@@ -56,4 +57,8 @@ export class AvalancheModule implements Module {
|
|
|
56
57
|
return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };
|
|
57
58
|
}
|
|
58
59
|
}
|
|
60
|
+
|
|
61
|
+
static getHashedBlockchainId({ blockchainId, isTestnet }: { blockchainId: string; isTestnet?: boolean }): string {
|
|
62
|
+
return hashBlockchainId({ blockchainId, isTestnet });
|
|
63
|
+
}
|
|
59
64
|
}
|
package/tsconfig.json
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
"extends": "@internal/tsconfig/tsconfig.base.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"outDir": "./dist",
|
|
5
|
+
"declaration": false,
|
|
5
6
|
"incremental": false // Need to turn off because of tsup dts
|
|
6
7
|
},
|
|
7
|
-
"include": ["src"]
|
|
8
|
+
"include": ["src"],
|
|
9
|
+
"references": [
|
|
10
|
+
{
|
|
11
|
+
"path": "../../packages-internal/utils/tsconfig.json"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
8
14
|
}
|