use index to add/remove an oracle, add intergration example

This commit is contained in:
czl1378 2020-12-09 23:38:31 +08:00
parent af769d64d1
commit f5fa78c95f
23 changed files with 1149 additions and 1464 deletions

4
.env Normal file
View File

@ -0,0 +1,4 @@
NETWORK=dev
DEPLOY_FILE=deploy.json
ADMIN_MNEMONIC="summer fuel twin history item learn flip marble ginger knee mix ten"
ORACLE_MNEMONIC="pet retreat peasant wing search rug dwarf high city pill giggle dinner"

4
.gitignore vendored
View File

@ -1,2 +1,4 @@
/node_modules
/program/target
/program/target
/intergration-example/target
yarn.lock

View File

@ -13,7 +13,7 @@ yarn install
Setup a wallet for the flux aggregator admin:
```
yarn generate-wallet
yarn solink generate-wallet
address: 7YMUUCzZir7AAuoy4CtZih9JFBqYwtQiCxjA5dtqwRxU
mnemonic: wine vault fancy enhance trade dolphin hard traffic social butter client pave
@ -62,7 +62,7 @@ feed initialized, pubkey: AUK9X6QLgauAUvEA3Ajc91fZytb9ccA7qVR72ErDFNg2
Next, we create a separate wallet to control oracles:
```
yarn generate-wallet
yarn solink generate-wallet
address: FosLwbttPgkEDv36VJLU3wwXcBSSoUGkh7dyZPsXNtT4
mnemonic: amount smoke bar coil current trial toward minimum model pass moral liberty
@ -82,6 +82,7 @@ Next we create a new oracle to the feed we've created previously, and set its ow
```
yarn solink add-oracle \
--index 0 \
--feedAddress AUK9X6QLgauAUvEA3Ajc91fZytb9ccA7qVR72ErDFNg2 \
--oracleName solink-test \
--oracleOwner FosLwbttPgkEDv36VJLU3wwXcBSSoUGkh7dyZPsXNtT4

Binary file not shown.

View File

@ -1,10 +1,10 @@
{
"aggregatorProgram": {
"pubkey": "9KXbVqUrMgtti7Jx4rrV1NqXjQNxWaKgtYCEwJ8AESS5",
"secret": "a2b92fa9514ac18a40c2bc895db0f97cabc1870205a74d84a0fb4a8167e6cba37b9c8b296cb261a7f3b17b294c72c4b6d427ab499b4ad6323b844289bcfebf6a"
"pubkey": "HFHbe2uckzz9Xh633mbJPYcukzpyJRVcwL87fUrVddiq",
"secret": "46046129c833cdf42b541357fc7c0667a369ca8ab7aed7f4ce653c710d3650b2f163e380895f9fa347f75834f3be6196919bacc3c769338b7f15d6a4ee1e814a"
},
"btc:usd": {
"pubkey": "AUK9X6QLgauAUvEA3Ajc91fZytb9ccA7qVR72ErDFNg2",
"secret": "233f1f8df9bf0e98c054f4b012eba361ec5050d93f7b06cdb0b2d0242cdf9a2e8cb862071d89cbf390570fa521c0daff5ca0e47f767dc32940801b449e50ad1b"
"pubkey": "2jReuMRoYi3pKTF8YLnZEvT2bXcw56SdBxvssrVzu41v",
"secret": "9feec34f2157b6deefc08c2132b321fb379b65fe6901d07e9a4df69fe8bad75a19b9f4ea63a705fc4b822d70015680c6f1cb0d4df30548a673604680760a9d11"
}
}

729
intergration-example/Cargo.lock generated Normal file
View File

@ -0,0 +1,729 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bincode"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
dependencies = [
"byteorder",
"serde",
]
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array 0.12.3",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]]
name = "bs58"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
[[package]]
name = "bv"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340"
dependencies = [
"feature-probe",
"serde",
]
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "curve25519-dalek"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5"
dependencies = [
"byteorder",
"digest",
"rand_core",
"subtle",
"zeroize",
]
[[package]]
name = "derivative"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array 0.12.3",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "feature-probe"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
[[package]]
name = "flux-aggregator"
version = "0.1.0"
dependencies = [
"arrayref",
"byteorder",
"num-derive",
"num-traits",
"num_enum",
"solana-program",
"spl-token",
"thiserror",
]
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
"serde",
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066"
dependencies = [
"derivative",
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro-crate"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
dependencies = [
"toml",
]
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
]
[[package]]
name = "regex"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_bytes"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sha2"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
dependencies = [
"block-buffer",
"digest",
"fake-simd",
"opaque-debug",
]
[[package]]
name = "solana-frozen-abi"
version = "1.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5ab6ad3dda6a3d95d19603eeedc65689d8125eafb3e23c6a1e01ab8a6ba60c"
dependencies = [
"bs58",
"bv",
"generic-array 0.14.4",
"log",
"memmap",
"rustc_version",
"serde",
"serde_derive",
"sha2",
"solana-frozen-abi-macro",
"solana-logger",
"thiserror",
]
[[package]]
name = "solana-frozen-abi-macro"
version = "1.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffaa09aa938a67501479ed8a785071c6993f72c34e43f680db3ea7a2dadad9e7"
dependencies = [
"lazy_static",
"proc-macro2",
"quote",
"rustc_version",
"syn",
]
[[package]]
name = "solana-logger"
version = "1.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d949157d0b23eaf5758b427d90741d2a90751c4e3dfee028f5726ab8b36e769"
dependencies = [
"env_logger",
"lazy_static",
"log",
]
[[package]]
name = "solana-program"
version = "1.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9c6cb16e8aa986bc0d2af8ec50628f7451bef9dac89924adf48302bd4fc755"
dependencies = [
"bincode",
"bs58",
"bv",
"curve25519-dalek",
"hex",
"itertools",
"lazy_static",
"log",
"num-derive",
"num-traits",
"rand",
"rustc_version",
"rustversion",
"serde",
"serde_bytes",
"serde_derive",
"sha2",
"solana-frozen-abi",
"solana-frozen-abi-macro",
"solana-logger",
"solana-sdk-macro",
"thiserror",
]
[[package]]
name = "solana-program-demo"
version = "0.1.0"
dependencies = [
"byteorder",
"flux-aggregator",
"solana-program",
]
[[package]]
name = "solana-sdk-macro"
version = "1.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "475a680cd175f2e256452e007c6f8622d3a1ab97ab36d26303b35576e24f340c"
dependencies = [
"bs58",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "spl-token"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f77fa0b41cbc82d1d7c8f2d914b49e9a1a7b6e32af952d03383fb989c42bc89"
dependencies = [
"arrayref",
"num-derive",
"num-traits",
"num_enum",
"solana-program",
"thiserror",
]
[[package]]
name = "subtle"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
[[package]]
name = "syn"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "toml"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
dependencies = [
"serde",
]
[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "zeroize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a"

View File

@ -0,0 +1,21 @@
[package]
name = "solana-program-demo"
version = "0.1.0"
authors = ["czl1378 <czl1378@126.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
solana-program = "1.4.8"
byteorder = "1.3"
flux-aggregator = { path = "../program", features = [ "no-entrypoint" ] }
[lib]
crate-type = ["cdylib", "lib"]
[features]
program = []
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -0,0 +1,163 @@
import {
Account,
Connection,
Version,
BpfLoader,
BPF_LOADER_PROGRAM_ID,
PublicKey,
LAMPORTS_PER_SOL,
SystemProgram,
TransactionInstruction,
Transaction,
sendAndConfirmTransaction,
} from '@solana/web3.js';
// @ts-ignore
import BufferLayout from 'buffer-layout';
import fs from 'fs';
import {newAccountWithLamports} from './util/new-account-with-lamports';
interface ConnectionResult {
connection: Connection;
version: Version;
}
interface LoadProgramResult {
programId: PublicKey;
pubkey: PublicKey;
}
const demoAccountDataLayout = BufferLayout.struct([
BufferLayout.u32('number'),
]);
/**
* Establish a connection to the cluster
*/
export async function establishConnection(url: string): Promise<ConnectionResult> {
let connection = new Connection(url, 'singleGossip');
const version = await connection.getVersion();
return {
connection, version
}
}
/**
* Caculate the pay fees
*/
export async function calculatePayfees(pathToProgram: string, connection: Connection): Promise<number> {
let fees = 0;
const {feeCalculator} = await connection.getRecentBlockhash();
// Calculate the cost to load the program
const data = fs.readFileSync(pathToProgram);
const NUM_RETRIES = 500; // allow some number of retries
fees +=
feeCalculator.lamportsPerSignature *
(BpfLoader.getMinNumSignatures(data.length) + NUM_RETRIES) +
(await connection.getMinimumBalanceForRentExemption(data.length));
// Calculate the cost to fund the greeter account
fees += await connection.getMinimumBalanceForRentExemption(
demoAccountDataLayout.span,
);
// Calculate the cost of sending the transactions
fees += feeCalculator.lamportsPerSignature * 100; // wag
return fees;
}
/**
* Establish an account to pay for everything
*/
export async function establishPayer(fees: number, connection: Connection): Promise<Account> {
// Fund a new payer via airdrop
let payerAccount = await newAccountWithLamports(connection, fees);
return payerAccount;
}
/**
* Load the hello world BPF program if not already loaded
*/
export async function loadProgram(pathToProgram: string, payerAccount: Account, connection: Connection): Promise<LoadProgramResult> {
const data = fs.readFileSync(pathToProgram);
// const programAccount = await accountFromMnemonic("spin canyon tuition upset pioneer celery liquid conduct boy bargain dust seed");
const programAccount = new Account();
console.log("empty account:", programAccount.publicKey.toBase58());
await BpfLoader.load(
connection,
payerAccount,
programAccount,
data,
BPF_LOADER_PROGRAM_ID,
);
const programId = programAccount.publicKey;
// Create the demo account
const demoAccount = new Account();
const demoPubkey = demoAccount.publicKey;
const space = demoAccountDataLayout.span;
const lamports = await connection.getMinimumBalanceForRentExemption(
demoAccountDataLayout.span,
);
let tx = SystemProgram.createAccount({
fromPubkey: payerAccount.publicKey,
newAccountPubkey: demoPubkey,
lamports,
space,
programId,
});
console.log(tx);
const transaction = new Transaction().add(
tx
);
await sendAndConfirmTransaction(
connection,
transaction,
[payerAccount, demoAccount],
{
commitment: 'singleGossip',
preflightCommitment: 'singleGossip',
},
);
return {
programId, pubkey: demoPubkey
};
}
/**
* intialize
*/
export async function initialize(num: string, pubkey: PublicKey, programId: PublicKey, payerAccount: Account, connection: Connection): Promise<void> {
const instruction = new TransactionInstruction({
keys: [{pubkey, isSigner: false, isWritable: true}],
programId,
data: Buffer.from(num), // All instructions are hellos
});
await sendAndConfirmTransaction(
connection,
new Transaction().add(instruction),
[payerAccount],
{
commitment: 'singleGossip',
preflightCommitment: 'singleGossip',
},
);
}

View File

@ -0,0 +1,58 @@
import { LAMPORTS_PER_SOL, Account, PublicKey } from '@solana/web3.js';
import {
establishConnection,
calculatePayfees,
establishPayer,
loadProgram,
initialize,
} from './demo';
const solPath = '../build/solana_program_demo.so';
function randNumber(): number {
let num = Math.random() * 100;
return parseInt(num + '');
}
async function main() {
try {
console.log("Establish connection...");
const res = await establishConnection('http://localhost:8899');
console.log("Connection to cluster established: ", res.version);
const { connection } = res;
console.log("Caculate pay for fees...");
const fees = await calculatePayfees(solPath, connection);
console.log("Fees:", fees);
console.log("Establish payer...");
const payer = await establishPayer(fees, connection);
console.log("payer balance:", await connection.getBalance(payer.publicKey));
console.log("Using account ", payer.publicKey.toBase58(), " to load the program.");
const program = await loadProgram(solPath, payer, connection);
const { programId, pubkey } = program;
console.log('Program loaded to account:', programId.toBase58());
console.log("Prepare to initialize program...");
await initialize(
'BTC/USD',
// the aggregator feed address
new PublicKey('2jReuMRoYi3pKTF8YLnZEvT2bXcw56SdBxvssrVzu41v'),
programId,
payer,
connection
);
} catch(err) {
console.log(err);
}
}
main();

View File

@ -0,0 +1,16 @@
import {Account} from '@solana/web3.js';
import nacl from "tweetnacl"
import * as bip39 from "bip39"
import * as bip32 from "bip32"
export default async function accountFromMnemonic(mnemonic: string) {
const seed = await bip39.mnemonicToSeed(mnemonic);
const base = bip32.fromSeed(seed).derivePath(`m/501'/0'/0`);
const account = new Account(nacl.sign.keyPair.fromSeed(base.privateKey as any).secretKey);
return account;
}

View File

@ -0,0 +1,21 @@
import {Account, Connection} from '@solana/web3.js';
export async function newAccountWithLamports(
connection: Connection,
lamports = 1000000,
): Promise<Account> {
const account = new Account();
let retries = 10;
await connection.requestAirdrop(account.publicKey, lamports);
for (;;) {
if (lamports == (await connection.getBalance(account.publicKey))) {
return account;
}
if (--retries <= 0) {
break;
}
console.log(`Airdrop retry ${retries}`);
}
throw new Error(`Airdrop of ${lamports} failed`);
}

View File

@ -0,0 +1,36 @@
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
info,
entrypoint::ProgramResult,
program_error::{ProgramError},
pubkey::Pubkey,
};
use flux_aggregator;
entrypoint!(process_instruction);
// Program entrypoint's implementation
fn process_instruction(
_program_id: &Pubkey, // Public key of the account the hello world program was loaded into
accounts: &[AccountInfo], // The account to say hello to
_instruction_data: &[u8], // A number to store
) -> ProgramResult {
let accounts_iter = &mut accounts.iter();
// the account to store data
let aggregator_info = next_account_info(accounts_iter)?;
let value = flux_aggregator::get_submission_value(aggregator_info)?;
// show the value and then return error
// to demonstrate we've got the aggregator value
info!(&format!("aggregator value: {:?}", value));
return Err(ProgramError::MissingRequiredSignature);
}

View File

@ -0,0 +1,6 @@
#![deny(missing_docs)]
//! A simple program that return success.
#[cfg(not(feature = "no-entrypoint"))]
mod entrypoint;
// Export current sdk types for downstream users building with a different sdk version
pub use solana_program;

View File

@ -15,7 +15,8 @@
"@solana/web3.js": "^0.87.1",
"buffer-layout": "^1.2.0",
"commander": "^6.2.0",
"dotenv": "^8.2.0"
"dotenv": "^8.2.0",
"solray": "git+https://github.com/defactojob/solray.git"
},
"devDependencies": {
"@tsconfig/recommended": "^1.0.1",

View File

@ -40,6 +40,9 @@ pub enum Error {
/// Aggregator key not match
#[error("Aggregator key not match")]
AggregatorKeyNotMatch,
/// Index have been used
#[error("Index have been used")]
IndexHaveBeenUsed,
}
impl From<Error> for ProgramError {

View File

@ -37,14 +37,16 @@ pub enum Instruction {
/// 0. `[writable]` The aggregator.
/// 1. `[signer]` The aggregator's authority.
AddOracle {
/// add to index
index: u8,
/// Is usually the oracle name
description: [u8; 32],
},
/// Remove an oracle
RemoveOracle {
/// The oracle key
oracle: Pubkey,
/// index
index: u8,
},
/// Called by oracles when they have witnessed a need to update
@ -71,33 +73,33 @@ impl Instruction {
Ok(match tag {
0 => {
let (submit_interval, rest) = rest.split_at(4);
info!("1");
let submit_interval = submit_interval
.try_into()
.ok()
.map(u32::from_le_bytes)
.ok_or(InvalidInstruction)?;
info!("2");
let (min_submission_value, rest) = rest.split_at(8);
let min_submission_value = min_submission_value
.try_into()
.ok()
.map(u64::from_le_bytes)
.ok_or(InvalidInstruction)?;
info!("3");
let (max_submission_value, rest) = rest.split_at(8);
let max_submission_value = max_submission_value
.try_into()
.ok()
.map(u64::from_le_bytes)
.ok_or(InvalidInstruction)?;
info!("4");
let (description, _rest) = rest.split_at(32);
let description = description
.try_into()
.ok()
.ok_or(InvalidInstruction)?;
info!("5");
Self::Initialize {
submit_interval,
min_submission_value,
@ -107,6 +109,9 @@ impl Instruction {
},
1 => {
let (&index, rest) = rest.split_first().ok_or(InvalidInstruction)?;
info!(format!("das index: {:?}", index));
let (description, _rest) = rest.split_at(32);
let description = description
.try_into()
@ -114,13 +119,13 @@ impl Instruction {
.ok_or(InvalidInstruction)?;
Self::AddOracle {
description,
index, description,
}
},
2 => {
let (oracle, _rest) = Self::unpack_pubkey(rest)?;
let (&index, _rest) = rest.split_first().ok_or(InvalidInstruction)?;
Self::RemoveOracle {
oracle,
index,
}
},
3 => {

View File

@ -42,19 +42,21 @@ impl Processor {
)
},
Instruction::AddOracle {
index,
description,
} => {
info!("Instruction: AddOracle");
info!(format!("index: {:?}", index));
Self::process_add_oracle(
accounts, description,
accounts, index, description,
)
},
Instruction::RemoveOracle {
oracle,
index,
} => {
info!("Instruction: RemoveOracle");
Self::process_remove_oracle(
accounts, oracle,
accounts, index,
)
},
Instruction::Submit {
@ -140,6 +142,7 @@ impl Processor {
/// 4. `[signer]` The aggregator owner
pub fn process_add_oracle(
accounts: &[AccountInfo],
index: u8,
description: [u8; 32],
) -> ProgramResult {
@ -174,18 +177,25 @@ impl Processor {
let mut submissions = aggregator.submissions;
// default submission
for s in submissions.iter_mut() {
if s.oracle == Pubkey::default() {
*s = Submission {
time: clock.unix_timestamp,
value: 0,
oracle: *oracle_info.key,
};
break;
}
let submission = &mut submissions[index as usize];
if submission.oracle == Pubkey::default() {
submission.oracle = *oracle_info.key;
} else {
return Err(Error::IndexHaveBeenUsed.into());
}
// // default submission
// for s in submissions.iter_mut() {
// if s.oracle == Pubkey::default() {
// *s = Submission {
// time: clock.unix_timestamp,
// value: 0,
// oracle: *oracle_info.key,
// };
// break;
// }
// }
aggregator.submissions = submissions;
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
@ -212,7 +222,7 @@ impl Processor {
/// 1. `[signer]` The aggregator onwer.
pub fn process_remove_oracle(
accounts: &[AccountInfo],
oracle: Pubkey,
index: u8,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let aggregator_info = next_account_info(account_info_iter)?;
@ -235,19 +245,26 @@ impl Processor {
// remove submission
let mut submissions = aggregator.submissions;
let mut found = false;
for s in submissions.iter_mut() {
if s.oracle == oracle {
*s = Submission::default();
found = true;
break;
}
}
if !found {
let submission = &mut submissions[index as usize];
if submission.oracle != Pubkey::default() {
*submission = Submission::default();
} else {
return Err(Error::NotFoundOracle.into());
}
// let mut found = false;
// for s in submissions.iter_mut() {
// if s.oracle == oracle {
// *s = Submission::default();
// found = true;
// break;
// }
// }
// if !found {
// return Err(Error::NotFoundOracle.into());
// }
aggregator.submissions = submissions;
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
@ -428,6 +445,7 @@ impl PrintProgramError for Error {
Error::SubmissonCooling => info!("Submission cooling"),
Error::InsufficientWithdrawable => info!("Insufficient withdrawable"),
Error::AggregatorKeyNotMatch => info!("Aggregator key not match"),
Error::IndexHaveBeenUsed => info!("Index have been used"),
}
}
}

View File

@ -1 +0,0 @@
NETWORK=dev

View File

@ -56,6 +56,8 @@ interface InitializeInstructionParams extends InitializeParams {
}
interface AddOracleParams {
// oracle index
index: number;
owner: PublicKey;
description: string;
aggregator: PublicKey;
@ -68,11 +70,13 @@ interface AddOracleInstructionParams extends AddOracleParams {
}
interface RemoveOracleParams {
aggregator: PublicKey,
// oracle index
index: number;
aggregator: PublicKey;
// The oracle key
oracle: PublicKey,
oracle: PublicKey;
// To prove you are the aggregator owner
authority: Account,
authority: Account;
}
interface RemoveOracleInstructionParams extends RemoveOracleParams {
@ -193,6 +197,7 @@ export default class FluxAggregator extends BaseProgram {
private addOracleInstruction(params: AddOracleInstructionParams): TransactionInstruction {
const {
index,
oracle,
owner,
description,
@ -202,11 +207,13 @@ export default class FluxAggregator extends BaseProgram {
const layout = BufferLayout.struct([
BufferLayout.u8("instruction"),
BufferLayout.u8("index"),
BufferLayout.blob(32, "description"),
]);
return this.instructionEncode(layout, {
instruction: 1, // add oracle instruction
index,
description: Buffer.from(description),
}, [
{ write: oracle },
@ -226,19 +233,18 @@ export default class FluxAggregator extends BaseProgram {
private removeOracleInstruction(params: RemoveOracleInstructionParams): TransactionInstruction {
const {
aggregator,
oracle,
index,
authority,
} = params;
const layout = BufferLayout.struct([
BufferLayout.u8("instruction"),
publicKey("oracle"),
BufferLayout.u8("index"),
]);
return this.instructionEncode(layout, {
instruction: 2, // remove oracle instruction
oracle: oracle.toBuffer(),
index,
}, [
{ write: authority },
]);

View File

@ -189,18 +189,23 @@ cli
cli
.command("add-oracle")
.description("add an oracle to aggregator")
.option("--index <number>", "add to index (0-20)")
.option("--feedAddress <string>", "feed address")
.option("--oracleName <string>", "oracle name")
.option("--oracleOwner <string>", "oracle owner address")
.action(async (opts) => {
const { deployer, admin, aggregatorProgram } = await AdminContext.load()
const { admin, aggregatorProgram } = await AdminContext.load()
const { oracleName, oracleOwner, feedAddress } = opts
const { index, oracleName, oracleOwner, feedAddress } = opts
if (!index || index < 0 || index > 21) {
error("invalid index (0-20)")
}
const program = new FluxAggregator(admin, aggregatorProgram.publicKey)
log("add oracle...")
const oracle = await program.addOracle({
index,
owner: new PublicKey(oracleOwner),
description: oracleName.substr(0, 32).padEnd(32),
aggregator: new PublicKey(feedAddress),

View File

@ -102,7 +102,7 @@ export async function walletFromEnv(key: string, conn: Connection): Promise<Wall
export async function openDeployer(): Promise<Deployer> {
const deployFile = process.env.DEPLOY_FILE
if (!deployFile) {
throw new Error(`Set DEPLOY_FILE in .env`)
}

1411
yarn.lock

File diff suppressed because it is too large Load Diff