{"id":13651784,"url":"https://github.com/eostitan/delphioracle","last_synced_at":"2025-04-22T22:32:03.188Z","repository":{"id":130641192,"uuid":"151975838","full_name":"eostitan/delphioracle","owner":"eostitan","description":null,"archived":false,"fork":false,"pushed_at":"2023-10-26T14:16:04.000Z","size":785,"stargazers_count":39,"open_issues_count":9,"forks_count":38,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-01-24T04:15:08.232Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eostitan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-10-07T19:09:11.000Z","updated_at":"2023-01-30T23:35:42.000Z","dependencies_parsed_at":"2024-01-03T05:13:55.979Z","dependency_job_id":"f6e2c321-daa3-4c47-bc01-3065a3a90d75","html_url":"https://github.com/eostitan/delphioracle","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eostitan%2Fdelphioracle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eostitan%2Fdelphioracle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eostitan%2Fdelphioracle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eostitan%2Fdelphioracle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eostitan","download_url":"https://codeload.github.com/eostitan/delphioracle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250334042,"owners_count":21413496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T02:00:52.313Z","updated_at":"2025-04-22T22:32:02.898Z","avatar_url":"https://github.com/eostitan.png","language":"C++","funding_links":[],"categories":["Oracles","Developers"],"sub_categories":["Commercial Services","Libraries and Frameworks"],"readme":"![EOS TITAN](./eos_logo_white.jpg \"EOS TITAN\")\n\n[https://eostitan.com](https://eostitan.com)\n\n# DelphiOracle\n\nThe DelphiOracle contract acts as a multi-party source of truth, designed to provide the near-realtime price of the asset pairs to other smart contracts or to external users.\n\nThe contract allows the current top 105 block producers to push rates for various assets, at a maximum frequency of 1 minute per asset.\n\nWhen a new datapoint is pushed to the contract, the contract will use the median from the last 21 datapoints.\n\nThis provides strong DPOS byzantine fault tolerance guarantees, ensuring a reliable pricefeed even if up to 10 block producers are colluding or corrupt (once a sufficient number of BPs are pushing rates).\n\nConsumer contracts or external applications can retrieve the last price and use it for their needs.\n\nAs more block producers and oracles will begin pushing the value at a 1 minute interval, confidence and accuracy of the value will increase.\n\nThis repository provides the code to the contract, as well as an updating script written in node.js for oracles and block producers to use. \n\nIdeally, block producers acting as oracles should use their own mechanism to retrieve and aggregate the data, using multiple sources.\n\nA sample updating script using cryptocompare.com's api to retrieve the EOSUSD, EOSBTC and EOSCNY prices is provided as an example.\n\nView live rates on EOS Mainnet:\n\n[https://labs.eostitan.com/#/pricefeed-oracle](https://labs.eostitan.com/#/pricefeed-oracle)\n\n## Incentive mechanisms for BPs to push rates\n\nEach time a BP pushes a datapoint, a counter for this BP is incremented. The contract supports an EOS transfer notification handler which splits any EOS reward sent to the contract between BPs that are pushing rates, proportionally to the number of datapoints they have pushed.\n\nThis allows for anyone relying on this pricefeed to incentivize BPs to join and to push rates, simply by transferring any amount of EOS to the contract.\n\nBPs can claim these rewards by calling the claim function.\n\n```\ncleos push action delphioracle claim '{\"owner\":\"\u003caccount\u003e\"}' -p \u003caccount\u003e\n\n```\n\nIn addition, the contract act as a proxy, and automatically revotes every 10,000 datapoints for up to 30 BPs, ranking them by total number of datapoints contributed since inception.\n\n[https://www.alohaeos.com/vote/proxy/delphioracle](https://www.alohaeos.com/vote/proxy/delphioracle)\n\nUsers and dApps relying on DelphiOracle are invited to delegate their votes to it, and support contributing BPs.\n\n## Push values to the contract\n\nQualified block producers can call the contract up to once every minute to provide the current price of an asset pair.\n\n**Note:**\n\n*for EOS/USD (eosusd) and EOS/CNY (eoscny), price must be pushed as integer, using the last 4 digits to represent the value after the decimal separator (10,000th of a dollar / yuan precision)*\n\n*for EOS/BTC (eosbtc), price must be pushed as integer, using the last 8 digits to represent the value after the decimal separator (100,000,000th of a bitcoin precision)*\n\nExample: a value for EOS/USD of $5.85 pushed by block producer acryptotitan to delphioracle contract would look like this:\n\n```\ncleos push action delphioracle write '{\"owner\":\"acryptotitan\", \"quotes\": [{\"value\":58500, \"pair\":\"eosusd\"}]}' -p acryptotitan@active\n```\n\n## Set up and run updater.js\n\nUpdater.js is a nodejs module meant to retrieve the EOS/USD price using cryptocompare.com's API, and push the result to the DelphiOracle smart contract automatically and continuously, with the help of CRON.\n\n```\ncd scripts\nnpm install\n```\n\n**Required:** Copy sample.env to .env and update values\n\nExample file for CryptoKylin:\n\n```\nEOS_PROTOCOL='http'\nEOS_HOST='api.kylin.alohaeos.com'\nEOS_PORT='80'\nEOS_KEY='5... \u003creplace with private key\u003e'\nEOS_CHAIN='5fff1dae8dc8e2fc4d5b23b2c7665c97f9e9d8edf2b6485a86ba311c25639191'\nORACLE=\"acryptotitan\"\nCONTRACT=\"delphioracle\"\nFREQ=15000\nORACLE_PERMISSION=\"active\"\n```\n\nRun script (once):\n\n```\nnode updater.js\n```\n\nRun script every minute via CRON:\n\n```\ncrontab -e\n```\n\nAnd add the following entry:\n\n\n```\n* * * * * /path/to/contract/folder/scripts/update.sh\n```\n\n\n\n**Optional:** Create a custom permission for oracle write action. Custom oracle permission can be supplied in the .env file under ORACLE_PERMISSION (defaults to active).\n\n```\ncleos set account permission \u003ceosaccount\u003e \u003cpermissionname\u003e \u003ceoskey\u003e \u003cpermissionparent\u003e\ncleos set action permission \u003ceosaccount\u003e \u003ceoscontract\u003e \u003caction\u003e \u003cpermissionname\u003e\n```\n\nExample:\n\n```\ncleos set account permission eostitantest oracle EOS6JhWzHJWystQmEv8VbXTHVagf5LKRVjkowwsdqCNYDFxYZQEJ9 active\ncleos set action permission eostitantest delphioracle write oracle\n```\n\n## Retrieve the last data point\n\n**Note:** *Use average / 10^quote_precision to get the actual value. `quote_precision` can be found in the `pairs` table*\n\n```\ncleos get table \u003ceoscontract\u003e \u003ceoscontract\u003e pairs\n```\n\n```\ncleos get table \u003ceoscontract\u003e eosusd datapoints --limit 1\n```\n\nSample output:\n```\n{\n  \"rows\": [{\n      \"id\": \"0\",\n      \"owner\": \"acryptotitan\",\n      \"value\": 56800,\n      \"median\": 56863,\n      \"timestamp\": \"1564096083\"\n    }\n  ],\n  \"more\": true\n}\n```\n\n## RNG Data Source\n\nQualified block producers can call the contract up to once every minute to provide a random source of data for the DelphiOracle RNG.\n\nExample: a source of data pushed by block producer acryptotitan to delphioracle contract would look like this:\n\n```\ncleos push action delphioracle writehash '{\"owner\":\"acryptotitan\", \"hash\":\"559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd\", \"reveal\":\"\"}' -p acryptotitan@active\ncleos push action delphioracle writehash '{\"owner\":\"acryptotitan\", \"hash\":\"df7e70e5021544f4834bbee64a9e3789febc4be81470df629cad6ddb03320a5c\", \"reveal\":\"A\"}' -p acryptotitan@active\ncleos push action delphioracle writehash '{\"owner\":\"acryptotitan\", \"hash\":\"6b23c0d5f35d1b11f9b683f0b0a617355deb11277d91ae091d399c655b87940d\", \"reveal\":\"B\"}' -p acryptotitan@active\ncleos push action delphioracle writehash '{\"owner\":\"acryptotitan\", \"hash\":\"3f39d5c348e5b79d06e842c114e6cc571583bbf44e4b0ebfda1a01ec05745d43\", \"reveal\":\"C\"}' -p acryptotitan@active\n```\n\n- `reveal` parameter must be empty string on first push.\n\n## Compile and deploy delphioracle.cpp (using eosio.cdt v.1.6.x)\n\n```\ngit clone https://github.com/eostitan/delphioracle\ncd delphioracle\ncd build\ncmake .. \u0026\u0026 make\n./deploy.sh \u003ceoscontract\u003e\n```\n\n## Running the contract locally\n\nIf you're querying the contract from your own and need it to run on the local node for testing purposes, you'll need to first create the required account, compile the contract and deploy it.  However, before compiling you'll need to edit the source to comment out a line that checks for your account to be a \"qualified oracle\".  This will prevent you from posting prices.  The line, in the `src/delphioracle.cpp`, within the `delphioracle::write` method is this:\n```\ncheck(check_oracle(owner), \"account is not a qualified oracle\");\n```\ncomment it out by prepending the line with `//`.  Next run the following ($PK below should contain the value of your private key):\n\n```\ncleos create account eosio delphioracle $PK $PK -p eosio@active\ncd delphioracle\neosio-cpp  -I include/delphioracle/ src/delphioracle.cpp -o delphioracle.wasm --abigen\ncleos set contract delphioracle . delphioracle.wasm delphioracle.abi -p delphioracle@active\n```\nOnce running, the contract needs to be configured:\n```\ncd scripts\ncleos push action delphioracle configure  \"$(cat configure.json)\" -p delphioracle\n```\nand finally, a price can be pushed up for the EOS/USD pair:\n```\ncleos push action delphioracle write '{\"owner\":\"MyAccount\", \"quotes\": [{\"value\":58500,\"pair\":\"eosusd\"}]}' -p MyAccount@active\n```\nHowever, as developers are likely to prefer the \"median\" field over the \"value\" field, the above needs to be run 20 times before median gets populated.  Of course, the contract throttles traffic so only 1 write per minute is allowed.  The developer can run this:\n```\nfor i in {1..21}; do cleos push action delphioracle write '{\"owner\":\"MyAccont\", \"quotes\": [{\"value\":56000,\"pair\":\"eosusd\"}]}' -p MyAccount@active; sleep 60; done\n```\nYou can now check the table to make sure your price is there:\n```\ncleos get table --limit 100 delphioracle eosusd datapoints\n```\nif you have `jq` installed, you can show the first record, which should contain your price, like this:\n```\ncleos get table --limit 100 delphioracle eosusd datapoints |jq .rows[0]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feostitan%2Fdelphioracle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feostitan%2Fdelphioracle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feostitan%2Fdelphioracle/lists"}