Skip to content

Commit 6d7fb2a

Browse files
authored
Secure Mint EA (#3902)
* Secure Mint EA * Add tests * Fix test * Rename latestRelevantBlocks
1 parent 7230c63 commit 6d7fb2a

24 files changed

+1471
-0
lines changed

.changeset/cold-boats-sniff.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@chainlink/secure-mint-adapter': major
3+
---
4+
5+
First release

.pnp.cjs

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

packages/composites/secure-mint/CHANGELOG.md

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Chainlink External Adapter for secure-mint
2+
3+
This README will be generated automatically when code is merged to `main`. If you would like to generate a preview of the README, please run `yarn generate:readme secure-mint`.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "@chainlink/secure-mint-adapter",
3+
"version": "0.0.0",
4+
"description": "Chainlink secure-mint adapter.",
5+
"keywords": [
6+
"Chainlink",
7+
"LINK",
8+
"blockchain",
9+
"oracle",
10+
"secure-mint"
11+
],
12+
"main": "dist/index.js",
13+
"types": "dist/index.d.ts",
14+
"files": [
15+
"dist"
16+
],
17+
"repository": {
18+
"url": "https://github.com/smartcontractkit/external-adapters-js",
19+
"type": "git"
20+
},
21+
"license": "MIT",
22+
"scripts": {
23+
"clean": "rm -rf dist && rm -f tsconfig.tsbuildinfo",
24+
"prepack": "yarn build",
25+
"build": "tsc -b",
26+
"server": "node -e 'require(\"./index.js\").server()'",
27+
"server:dist": "node -e 'require(\"./dist/index.js\").server()'",
28+
"start": "yarn server:dist"
29+
},
30+
"devDependencies": {
31+
"@types/jest": "^29.5.14",
32+
"@types/node": "22.14.1",
33+
"ethers": "^6.14.3",
34+
"nock": "13.5.6",
35+
"typescript": "5.8.3"
36+
},
37+
"dependencies": {
38+
"@chainlink/external-adapter-framework": "2.6.0",
39+
"tslib": "2.4.1"
40+
}
41+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'
2+
3+
export const config = new AdapterConfig(
4+
{
5+
SECURE_MINT_INDEXER_URL: {
6+
description: 'Url to secure-mint-indexer',
7+
type: 'string',
8+
required: true,
9+
},
10+
BITGO_RESERVES_EA_URL: {
11+
description: 'Url to Bitgo Reserves EA',
12+
type: 'string',
13+
default: '',
14+
},
15+
16+
BACKGROUND_EXECUTE_MS: {
17+
description:
18+
'The amount of time the background execute should sleep before performing the next request',
19+
type: 'number',
20+
default: 1_000,
21+
},
22+
},
23+
{
24+
// Unlike regular EA where input is fixed for a specifc feed, this EA,
25+
// input is dynamic for a feed. Hence we would want to have
26+
// - a small subscription set (as old request will not be used once we've moved on)
27+
// - a small TTL on subscriptions
28+
// - a small cache on result
29+
envDefaultOverrides: {
30+
SUBSCRIPTION_SET_MAX_ITEMS: 1000,
31+
WARMUP_SUBSCRIPTION_TTL: 60_000,
32+
CACHE_MAX_AGE: 60_000,
33+
},
34+
},
35+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { endpoint as mintable } from './mintable'
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
2+
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
3+
import { AdapterInputError } from '@chainlink/external-adapter-framework/validation/error'
4+
import { config } from '../config'
5+
import { mintableTransport } from '../transport/mintable'
6+
import { IndexerResponse } from '../transport/supply'
7+
8+
export const inputParameters = new InputParameters(
9+
{
10+
token: {
11+
required: true,
12+
type: 'string',
13+
description: 'Name of the token',
14+
},
15+
reserves: {
16+
required: true,
17+
type: 'string',
18+
description: 'Name of the reserve data provider',
19+
options: ['Bitgo'],
20+
},
21+
supplyChains: {
22+
required: true,
23+
type: 'string',
24+
array: true,
25+
description: 'List of chains the token is on',
26+
},
27+
supplyChainBlocks: {
28+
required: true,
29+
type: 'number',
30+
array: true,
31+
description: 'The target block correspond to each chain in supplyChains',
32+
},
33+
},
34+
[
35+
{
36+
token: 'token1',
37+
reserves: 'Bitgo',
38+
supplyChains: ['1', '56'],
39+
supplyChainBlocks: [100, 400],
40+
},
41+
],
42+
)
43+
44+
export type BaseEndpointTypes = {
45+
Parameters: typeof inputParameters.definition
46+
Response: {
47+
Result: number
48+
Data: {
49+
overmint: boolean
50+
mintables: {
51+
[key: string]: {
52+
mintable: string
53+
block: number
54+
}
55+
}
56+
reserveInfo: {
57+
reserveAmount: string
58+
timestamp: number
59+
}
60+
latestBlocks: {
61+
[key: string]: number
62+
}
63+
supplyDetails: IndexerResponse
64+
}
65+
}
66+
Settings: typeof config.settings
67+
}
68+
69+
export const endpoint = new AdapterEndpoint({
70+
name: 'mintable',
71+
transport: mintableTransport,
72+
inputParameters,
73+
customInputValidation: (req, adapterSettings): AdapterInputError | undefined => {
74+
const { reserves, supplyChains, supplyChainBlocks } = req.requestContext.data
75+
if (supplyChains.length !== supplyChainBlocks.length) {
76+
throw new AdapterInputError({
77+
statusCode: 400,
78+
message: `supplyChains and supplyChainBlocks do not have the same length`,
79+
})
80+
}
81+
if (reserves === 'Bitgo' && adapterSettings.BITGO_RESERVES_EA_URL.length === 0) {
82+
throw new AdapterInputError({
83+
statusCode: 400,
84+
message: `Error: missing environment variable BITGO_RESERVES_EA_URL`,
85+
})
86+
}
87+
return
88+
},
89+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
2+
import { Adapter } from '@chainlink/external-adapter-framework/adapter'
3+
import { config } from './config'
4+
import { mintable } from './endpoint'
5+
6+
export const adapter = new Adapter({
7+
defaultEndpoint: mintable.name,
8+
name: 'SECURE_MINT',
9+
config,
10+
endpoints: [mintable],
11+
})
12+
13+
export const server = (): Promise<ServerInstance | undefined> => expose(adapter)

0 commit comments

Comments
 (0)