Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
3 changes: 3 additions & 0 deletions packages/sources/copper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Chainlink External Adapter for copper

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 copper`.
42 changes: 42 additions & 0 deletions packages/sources/copper/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@chainlink/copper-adapter",
"version": "0.0.0",
"description": "Chainlink copper adapter.",
"keywords": [
"Chainlink",
"LINK",
"blockchain",
"oracle",
"copper"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"url": "https://github.com/smartcontractkit/external-adapters-js",
"type": "git"
},
"license": "MIT",
"scripts": {
"clean": "rm -rf dist && rm -f tsconfig.tsbuildinfo",
"prepack": "yarn build",
"build": "tsc -b",
"server": "node -e 'require(\"./index.js\").server()'",
"server:dist": "node -e 'require(\"./dist/index.js\").server()'",
"start": "yarn server:dist"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"@types/node": "22.14.1",
"nock": "13.5.6",
"typescript": "5.8.3"
},
"dependencies": {
"@chainlink/external-adapter-framework": "2.7.0",
"@types/crypto-js": "4.2.2",
"crypto-js": "4.2.0",
"tslib": "2.4.1"
}
}
26 changes: 26 additions & 0 deletions packages/sources/copper/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'

export const config = new AdapterConfig({
API_KEY: {
description: 'An API key for Data Provider - Copper',
type: 'string',
required: true,
sensitive: true,
},
API_SECRET: {
description: 'An API secret for Data Provider - Copper',
type: 'string',
required: true,
sensitive: true,
},
API_ENDPOINT: {
description: 'An API endpoint for Data Provider - Copper',
type: 'string',
default: 'https://api.copper.co',
},
BACKGROUND_EXECUTE_MS: {
description: 'Background execute time in milliseconds',
type: 'number',
default: 1000,
},
})
3 changes: 3 additions & 0 deletions packages/sources/copper/src/config/overrides.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"copper": {}
}
1 change: 1 addition & 0 deletions packages/sources/copper/src/endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { endpoint as solstice } from './solstice'
49 changes: 49 additions & 0 deletions packages/sources/copper/src/endpoint/solstice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { config } from '../config'
import { solsticeTransport } from '../transport/solstice'

export const inputParameters = new InputParameters(
{
portfolioId: {
required: true,
type: 'string',
description: 'portfolioId for Solstice on Copper',
},
currencies: {
required: true,
array: true,
type: 'string',
description: 'currencies for Solstice on Copper',
},
},
[
{
portfolioId: '1134710216',
currencies: ['BTC', 'ETH', 'SOL', 'LTC', 'NEAR', 'USDC', 'USDT'],
},
],
)

export type BaseEndpointTypes = {
Parameters: typeof inputParameters.definition
Response: {
Result: string
Data: {
result: string
decimals: number
exchangeBalances: string[]
rate: {
value: string
decimal: number
}
}
}
Settings: typeof config.settings
}

export const endpoint = new AdapterEndpoint({
name: 'solstice',
transport: solsticeTransport,
inputParameters,
})
13 changes: 13 additions & 0 deletions packages/sources/copper/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
import { Adapter } from '@chainlink/external-adapter-framework/adapter'
import { config } from './config'
import { solstice } from './endpoint'

export const adapter = new Adapter({
defaultEndpoint: solstice.name,
name: 'COPPER',
config,
endpoints: [solstice],
})

export const server = (): Promise<ServerInstance | undefined> => expose(adapter)
137 changes: 137 additions & 0 deletions packages/sources/copper/src/transport/solstice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { EndpointContext } from '@chainlink/external-adapter-framework/adapter'
import { TransportDependencies } from '@chainlink/external-adapter-framework/transports'
import { SubscriptionTransport } from '@chainlink/external-adapter-framework/transports/abstract/subscription'
import { AdapterResponse, makeLogger, sleep } from '@chainlink/external-adapter-framework/util'
import { Requester } from '@chainlink/external-adapter-framework/util/requester'
import { AdapterError } from '@chainlink/external-adapter-framework/validation/error'
import { BaseEndpointTypes, inputParameters } from '../endpoint/solstice'

// import { getAssetPositions } from './mirrorX'
// import { btcToUSD } from './btcUSD'
// import { ethers } from 'ethers'
// import { Decimal } from 'decimal.js'
import { getActiveStakes, getOutstandingStakes, getPendingStakes, getWallets } from './utils'

const logger = makeLogger('Solstice')

type RequestParams = typeof inputParameters.validated

export class SolsticeTransport extends SubscriptionTransport<BaseEndpointTypes> {
baseUrl!: string
apiKey!: string
apiSecret!: string
requester!: Requester
// provider!: ethers.JsonRpcProvider

async initialize(
dependencies: TransportDependencies<BaseEndpointTypes>,
adapterSettings: BaseEndpointTypes['Settings'],
endpointName: string,
transportName: string,
): Promise<void> {
await super.initialize(dependencies, adapterSettings, endpointName, transportName)
this.requester = dependencies.requester
this.baseUrl = adapterSettings.API_ENDPOINT
this.apiKey = adapterSettings.API_KEY
this.apiSecret = adapterSettings.API_SECRET
// this.provider = new ethers.JsonRpcProvider(
// adapterSettings.ARBITRUM_RPC_URL,
// adapterSettings.ARBITRUM_RPC_CHAIN_ID,
// )
}
async backgroundHandler(context: EndpointContext<BaseEndpointTypes>, entries: RequestParams[]) {
await Promise.all(entries.map(async (param) => this.handleRequest(param)))
await sleep(context.adapterSettings.BACKGROUND_EXECUTE_MS)
}

async handleRequest(param: RequestParams) {
let response: AdapterResponse<BaseEndpointTypes['Response']>
try {
response = await this._handleRequest(param)
} catch (e) {
const errorMessage = e instanceof Error ? e.message : 'Unknown error occurred'
logger.error(e, errorMessage)
response = {
statusCode: (e as AdapterError)?.statusCode || 502,
errorMessage,
timestamps: {
providerDataRequestedUnixMs: 0,
providerDataReceivedUnixMs: 0,
providerIndicatedTimeUnixMs: undefined,
},
}
}
await this.responseCache.write(this.name, [{ params: param, response }])
}

async _handleRequest(
param: RequestParams,
): Promise<AdapterResponse<BaseEndpointTypes['Response']>> {
const providerDataRequestedUnixMs = Date.now()

const [wallets, activeStakes, pendingStakes, outstandingStakes] = await Promise.all([
getWallets(
param.portfolioId,
param.currencies,
this.baseUrl,
this.apiKey,
this.apiSecret,
this.requester,
),
getActiveStakes(
param.portfolioId,
param.currencies,
this.baseUrl,
this.apiKey,
this.apiSecret,
this.requester,
),
getPendingStakes(
param.portfolioId,
param.currencies,
this.baseUrl,
this.apiKey,
this.apiSecret,
this.requester,
),
getOutstandingStakes(
param.portfolioId,
param.currencies,
this.baseUrl,
this.apiKey,
this.apiSecret,
this.requester,
),
])

console.log(wallets, activeStakes.activeStakes, pendingStakes, outstandingStakes)

const result = 1
// BigInt(asset.sum.mul(new Decimal(10).pow(rate.decimal * 2)).toFixed(0)) / rate.value

return {
data: {
result: String(result),
decimals: 0, //rate.decimal,
exchangeBalances: [], //asset.exchangeBalances,
rate: {
value: '', //String(rate.value),
decimal: 0, //rate.decimal,
},
},
statusCode: 200,
result: String(result),
timestamps: {
providerDataRequestedUnixMs,
providerDataReceivedUnixMs: Date.now(),
providerIndicatedTimeUnixMs: undefined,
},
}
}

getSubscriptionTtlFromConfig(adapterSettings: BaseEndpointTypes['Settings']): number {
return adapterSettings.WARMUP_SUBSCRIPTION_TTL
}
}

export const solsticeTransport = new SolsticeTransport()
Loading
Loading