-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
256e663
commit 474ff46
Showing
13 changed files
with
1,161 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,13 +56,16 @@ | |
"@0glabs/0g-ts-sdk": "0.2.1", | ||
"@coinbase/coinbase-sdk": "0.10.0", | ||
"@deepgram/sdk": "^3.9.0", | ||
"@okxweb3/coin-bitcoin": "1.2.0", | ||
"@okxweb3/crypto-lib": "1.0.10", | ||
"@vitest/eslint-plugin": "1.0.1", | ||
"amqplib": "0.10.5", | ||
"csv-parse": "5.6.0", | ||
"ollama-ai-provider": "0.16.1", | ||
"optional": "0.1.4", | ||
"pnpm": "9.14.4", | ||
"sharp": "0.33.5", | ||
"tiny-secp256k1": "2.2.3", | ||
"tslog": "4.9.3" | ||
}, | ||
"packageManager": "[email protected]+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# `@elizaos/plugin-btcfun` | ||
|
||
This plugin provides actions and providers for interacting with bitcoin chains. | ||
|
||
--- | ||
|
||
## Configuration | ||
|
||
### Default Setup | ||
|
||
By default, **Bitcoin mainnet** is enabled. To use it, simply add your private key to the `.env` file: | ||
|
||
```env | ||
BTC_PRIVATE_KEY_WIF=your-private-key-here | ||
ADDRESS=your-address-here | ||
BTCFUN_API_URL=https://api-testnet-new.btc.fun |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import eslintGlobalConfig from "../../eslint.config.mjs"; | ||
|
||
export default [...eslintGlobalConfig]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "@elizaos/plugin-btcfun", | ||
"version": "0.1.7-alpha.2", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"@lifi/data-types": "5.15.5", | ||
"@lifi/sdk": "3.4.1", | ||
"@lifi/types": "16.3.0", | ||
"tsup": "8.3.5", | ||
"viem": "2.21.53" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"dev": "tsup --format esm --dts --watch", | ||
"test": "vitest run", | ||
"lint": "eslint --fix --cache ." | ||
}, | ||
"peerDependencies": { | ||
"whatwg-url": "7.1.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import { ByteArray, formatEther, parseEther, type Hex } from "viem"; | ||
import { | ||
composeContext, | ||
generateObjectDeprecated, | ||
HandlerCallback, | ||
ModelClass, | ||
type IAgentRuntime, | ||
type Memory, | ||
type State, | ||
} from "@elizaos/core"; | ||
|
||
import { networks, Psbt } from 'bitcoinjs-lib'; | ||
import { BIP32Factory } from 'bip32'; | ||
import {randomBytes} from 'crypto'; | ||
import * as ecc from 'tiny-secp256k1'; | ||
import { BtcWallet, privateKeyFromWIF } from "@okxweb3/coin-bitcoin"; | ||
import { base } from "@okxweb3/crypto-lib"; | ||
import { mintTemplate } from "../templates"; | ||
import {initBtcFunProvider} from "../providers/btcfun.ts"; | ||
export { mintTemplate }; | ||
|
||
export const btcfunMintAction = { | ||
name: "mint", | ||
description: "btcfun mint brc20", | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
_message: Memory, | ||
state: State, | ||
_options: any, | ||
callback?: HandlerCallback | ||
) => { | ||
console.log("btcfun action handler called"); | ||
const btcfunProvider = initBtcFunProvider(runtime); | ||
|
||
const chainCode = randomBytes(32); | ||
const bip32Factory = BIP32Factory(ecc); | ||
const network = networks.bitcoin; | ||
const privateKeyWif = runtime.getSetting("BTC_PRIVATE_KEY_WIF") ?? process.env.BTC_PRIVATE_KEY_WIF; | ||
let address = runtime.getSetting("ADDRESS") ?? process.env.ADDRESS; | ||
|
||
const privateKey = base.fromHex(privateKeyFromWIF(privateKeyWif, network)); | ||
const privateKeyHex = base.toHex(privateKey); | ||
const privateKeyBuffer = Buffer.from(privateKeyHex, 'hex'); | ||
const keyPair = bip32Factory.fromPrivateKey(privateKeyBuffer, chainCode, network); | ||
const publicKeyBuffer = Buffer.from(keyPair.publicKey); | ||
const publicKeyHex = publicKeyBuffer.toString('hex'); | ||
|
||
// Compose mint context | ||
const mintContext = composeContext({ | ||
state, | ||
template: mintTemplate, | ||
}); | ||
const content = await generateObjectDeprecated({ | ||
runtime, | ||
context: mintContext, | ||
modelClass: ModelClass.LARGE, | ||
}); | ||
let tick = content.inputToken; | ||
let mintcap = content.mintcap ?? runtime.getSetting("MINTCAP"); | ||
let mintdeadline = content.mintdeadline ?? runtime.getSetting("MINTDEADLINE"); | ||
let addressFundraisingCap = content.addressFundraisingCap ?? runtime.getSetting("ADDRESS_FUNDRAISING_CAP"); | ||
console.log("begin to mint token", tick, content) | ||
//validateBrc20 | ||
await btcfunProvider.validateBrc20(address, tick); | ||
console.log("validateBrc20 success") | ||
|
||
try { | ||
let {order_id, psbt_hex} = await btcfunProvider.createBrc20Order( | ||
publicKeyHex, address, publicKeyHex, address, 10, | ||
tick, addressFundraisingCap, mintdeadline, mintcap) | ||
const psbt = Psbt.fromHex(psbt_hex) | ||
let wallet = new BtcWallet() | ||
const toSignInputs = []; | ||
psbt.data.inputs.forEach((input, index)=>{ | ||
toSignInputs.push({ | ||
index: index, | ||
address: address, | ||
sighashTypes: [0], | ||
disableTweakSigner: false, | ||
}); | ||
}) | ||
|
||
let params = { | ||
type: 3, | ||
psbt: psbt_hex, | ||
autoFinalized: false, | ||
toSignInputs: toSignInputs, | ||
}; | ||
|
||
let signParams = { | ||
privateKey: privateKeyWif, | ||
data: params, | ||
}; | ||
let signedPsbtHex = await wallet.signTransaction(signParams); | ||
|
||
const txHash = await btcfunProvider.broadcastOrder(order_id, signedPsbtHex) | ||
console.log('signedPsbtHex: ', signedPsbtHex, 'orderID: ', order_id, 'txhash', txHash) | ||
if (callback) { | ||
callback({ | ||
text: `Successfully mint ${tick} tokens, mintcap ${mintcap}, mintdeadline ${mintdeadline}, addressFundraisingCap ${addressFundraisingCap} ,txhash ${txHash}`, | ||
content: { | ||
success: true, | ||
orderID: order_id, | ||
}, | ||
}); | ||
} | ||
} catch (error) { | ||
console.error('Error:', error); | ||
} | ||
}, | ||
template: mintTemplate, | ||
validate: async (runtime: IAgentRuntime) => { | ||
const privateKey = runtime.getSetting("BTC_PRIVATE_KEY_WIF"); | ||
return typeof privateKey === "string" && privateKey.length > 0; | ||
}, | ||
examples: [ | ||
[ | ||
{ | ||
user: "assistant", | ||
content: { | ||
text: "I'll help you mint 100000000 Party", | ||
action: "MINT_BRC20", | ||
}, | ||
}, | ||
{ | ||
user: "user", | ||
content: { | ||
text: "import token BRC20 `Party`, mintcap 100000, addressFundraisingCap 10 mintdeadline 864000", | ||
action: "MINT_BRC20", | ||
}, | ||
}, | ||
], | ||
], | ||
similes: ["MINT_BRC20","MINT_RUNES"], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {btcfunMintAction} from "./actions/btcfun.ts"; | ||
|
||
export * from "./providers/btcfun"; | ||
|
||
import type { Plugin } from "@elizaos/core"; | ||
|
||
export const btcfunPlugin: Plugin = { | ||
name: "btcfun", | ||
description: "btcfun plugin", | ||
providers: [], | ||
evaluators: [], | ||
services: [], | ||
actions: [btcfunMintAction], | ||
}; | ||
|
||
export default btcfunPlugin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import fetch from 'node-fetch'; | ||
import type {IAgentRuntime} from "@elizaos/core"; | ||
|
||
export const initBtcFunProvider = (runtime: IAgentRuntime) => { | ||
|
||
const btcfunApiURL = runtime.getSetting("BTCFUN_API_URL") ?? process.env.BTCFUN_API_URL | ||
if (!btcfunApiURL) { | ||
throw new Error("BTCFUN_API_URL is not set"); | ||
} | ||
|
||
return new BtcfunProvider(btcfunApiURL); | ||
}; | ||
|
||
export class BtcfunProvider { | ||
private apiUrl: string; | ||
|
||
constructor(apiUrl: string) { | ||
this.apiUrl = apiUrl; | ||
} | ||
|
||
async validateBrc20(address: string, ticker: string) { | ||
const response = await fetch(`${this.apiUrl}/api/v1/import/brc20_validate`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
address: address, | ||
ticker: ticker, | ||
}), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Error: ${response.statusText}`); | ||
} | ||
|
||
return response.json(); | ||
} | ||
|
||
async createBrc20Order(paymentFromPubKey: string, paymentFrom: string, ordinalsFromPubKey: string, ordinalsFrom: string, feeRate: number, tick: string, addressFundraisingCap: string, mintDeadline: number, mintCap: string) { | ||
const response = await fetch(`${this.apiUrl}/api/v1/import/brc20_order`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
payment_from_pub_key: paymentFromPubKey, | ||
payment_from: paymentFrom, | ||
ordinals_from_pub_key: ordinalsFromPubKey, | ||
ordinals_from: ordinalsFrom, | ||
fee_rate: feeRate, | ||
tick: tick, | ||
address_fundraising_cap: addressFundraisingCap, | ||
mint_deadline: mintDeadline, | ||
mint_cap: mintCap, | ||
}), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Error: ${response.statusText}`); | ||
} | ||
|
||
const result = await response.json(); | ||
|
||
if (result.code === "OK" && result.data) { | ||
const { order_id, psbt_hex } = result.data; | ||
return { order_id, psbt_hex }; | ||
} else { | ||
console.log("Invalid response", result) | ||
throw new Error("Invalid response"); | ||
} | ||
} | ||
|
||
async broadcastOrder(orderId: string, signedPsbtHex: string) { | ||
const response = await fetch(`${this.apiUrl}/api/v1/import/broadcast`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
order_id: orderId, | ||
signed_psbt_hex: signedPsbtHex, | ||
}), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Error: ${response.statusText}`); | ||
} | ||
const result = await response.json(); | ||
|
||
if (result.code === "OK" && result.data) { | ||
return result.data; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
export const mintTemplate = `Given the recent messages and wallet information below: | ||
{{recentMessages}} | ||
{{walletInfo}} | ||
Extract the following information about the requested token swap: | ||
- Input token symbol (the token being mint), eg: mint token abc | ||
- Input token mintcap eg: "10000" | ||
- Input token addressFundraisingCap everyone can offer eg: "10" | ||
- Input token mintdeadline ,duration Using seconds as the unit eg: 864000 | ||
Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined: | ||
\`\`\`json | ||
{ | ||
"inputToken": string | null, | ||
"mintcap": string | 1000, | ||
"addressFundraisingCap": string | 10, | ||
"mintdeadline" : number | 864000, | ||
} | ||
\`\`\` | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"extends": "../core/tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"rootDir": "./src", | ||
"typeRoots": [ | ||
"./node_modules/@types", | ||
"./src/types" | ||
], | ||
"declaration": true | ||
}, | ||
"include": [ | ||
"src" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { defineConfig } from "tsup"; | ||
|
||
export default defineConfig({ | ||
entry: ["src/index.ts"], | ||
outDir: "dist", | ||
sourcemap: true, | ||
clean: true, | ||
format: ["esm"], // Ensure you're targeting CommonJS | ||
external: [ | ||
"dotenv", // Externalize dotenv to prevent bundling | ||
"fs", // Externalize fs to use Node.js built-in module | ||
"path", // Externalize other built-ins if necessary | ||
"@reflink/reflink", | ||
"@node-llama-cpp", | ||
"https", | ||
"http", | ||
"agentkeepalive", | ||
"viem", | ||
"@lifi/sdk", | ||
"@okxweb3/crypto-lib", | ||
], | ||
}); |
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.