hyphacoop / distributed-press-organizing

15 stars 1 forks source link

Real-time balances from crowdfunding platforms #15

Closed benhylau closed 3 years ago

benhylau commented 3 years ago

🎟️ Re-ticketed from: #
📅 Due date: Dec 9, 2020
🎯 Success criteria: An unbranded but functional static webpage that displays real-time balances from our crowdfunding platforms.

Task Summary

Create a static website that displays real-time balances from:

This probably involves async javascript calls and may be proxied through a centralized service that we develop and operate.

To Do

benhylau commented 3 years ago

Gitcoin balance in ETH and ERC20 tokens using Etherscan

Get Ether Balance for a single Address

https://api.etherscan.io/api?module=account&action=balance&address=0xfb6F8D5DD687E77Aa9275a1Cb397dA3c23aAf342&tag=latest

{
  "status": "1",
  "message": "OK-Missing/Invalid API Key, rate limit of 1/5sec applied",
  "result": "0"
}

Get a list of "ERC20 - Token Transfer Events" by Address

https://api.etherscan.io/api?module=account&action=tokentx&address=0xfb6F8D5DD687E77Aa9275a1Cb397dA3c23aAf342&startblock=0&endblock=999999999&sort=asc

{
  "status": "1",
  "message": "OK-Missing/Invalid API Key, rate limit of 1/5sec applied",
  "result": [
    {
      "blockNumber": "10972761",
      "timeStamp": "1601589554",
      "hash": "0xe3ab67fec36d433054d89d97ce4b1704695d0bfca50b9a4a322beb64341d1b07",
      "nonce": "407",
      "blockHash": "0xab6550515980d055549278b410d924c4aad20a1b22700adb051fe8683a0e0b59",
      "from": "0xc92d76e01bd4e7ce25819c94fc6c3aea7b2cd155",
      "contractAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
      "to": "0xfb6f8d5dd687e77aa9275a1cb397da3c23aaf342",
      "value": "9500000000000000000",
      "tokenName": "Dai Stablecoin",
      "tokenSymbol": "DAI",
      "tokenDecimal": "18",
      "transactionIndex": "143",
      "gas": "175000",
      "gasPrice": "44000000000",
      "gasUsed": "83590",
      "cumulativeGasUsed": "12316278",
      "input": "deprecated",
      "confirmations": "352365"
    },
    {
      "blockNumber": "11009560",
      "timeStamp": "1602086598",
      "hash": "0x97677841cf135edc12d10b71c02698fbeb9702c674dfc4582c6a7a0fe4266cba",
      "nonce": "1907",
      "blockHash": "0xca94788b862b30d5f04dd8acbb58a4b449a5d66a1871abb14d19c6ff0ef4a8c8",
      "from": "0xe8c904dc650e6fcb3fe39cc82b40bd897c83d8fa",
      "contractAddress": "0xe4101d014443af2b7f6f9f603e904adc9faf0de5",
      "to": "0xfb6f8d5dd687e77aa9275a1cb397da3c23aaf342",
      "value": "1565339062889040128",
      "tokenName": "CLR7",
      "tokenSymbol": "CLR7",
      "tokenDecimal": "18",
      "transactionIndex": "29",
      "gas": "100000",
      "gasPrice": "114800000000",
      "gasUsed": "52215",
      "cumulativeGasUsed": "1801088",
      "input": "deprecated",
      "confirmations": "315566"
    },
    {
      "blockNumber": "11016400",
      "timeStamp": "1602180475",
      "hash": "0xb7b0ed0b2fed54c8597ea7c5a9a7c48d73c7553a4f9b4db9dd8c36c04001197d",
      "nonce": "2192",
      "blockHash": "0x67b63f524658162c63095b8f9189757556554bd7cc84e918fb4f1ec815245415",
      "from": "0xe8c904dc650e6fcb3fe39cc82b40bd897c83d8fa",
      "contractAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
      "to": "0xfb6f8d5dd687e77aa9275a1cb397da3c23aaf342",
      "value": "1565339062889040128",
      "tokenName": "Dai Stablecoin",
      "tokenSymbol": "DAI",
      "tokenDecimal": "18",
      "transactionIndex": "14",
      "gas": "100000",
      "gasPrice": "134399999999",
      "gasUsed": "37018",
      "cumulativeGasUsed": "602671",
      "input": "deprecated",
      "confirmations": "308726"
    }
  ]
}

Get ETHER Last Price

https://api.etherscan.io/api?module=stats&action=ethprice

{
  "status": "1",
  "message": "OK-Missing/Invalid API Key, rate limit of 1/5sec applied",
  "result": {
    "ethbtc": "0.03125",
    "ethbtc_timestamp": "1606274848",
    "ethusd": "594.83",
    "ethusd_timestamp": "1606274847"
  }
}
benhylau commented 3 years ago

Uphold API gives exchange rates for ERC20 tokens if we need: https://api.uphold.com/v0/ticker

benhylau commented 3 years ago

Open Collective REST API

Get collective info

https://opencollective.com/compost.json

{
  "slug": "compost",
  "currency": "CAD",
  "image": null,
  "balance": 1827105,
  "yearlyIncome": 1831560,
  "backersCount": 2,
  "contributorsCount": 0
}

Get members

https://opencollective.com/compost/members/all.json

[
  {
    "MemberId": 138907,
    "createdAt": "2020-11-07 20:24",
    "type": "USER",
    "role": "ADMIN",
    "isActive": true,
    "totalAmountDonated": 0,
    "lastTransactionAt": "2020-11-25 05:02",
    "lastTransactionAmount": 0,
    "profile": "https://opencollective.com/mai-sutton",
    "name": "Mai Ishikawa Sutton",
    "company": null,
    "description": null,
    "image": "https://www.gravatar.com/avatar/d9f49d37027c2a8821503056204ec234?default=404",
    "email": null,
    "twitter": "https://twitter.com/maira",
    "github": null,
    "website": "https://maisutton.net/"
  },
  {
    "MemberId": 138908,
    "createdAt": "2020-11-07 20:24",
    "type": "ORGANIZATION",
    "role": "HOST",
    "isActive": true,
    "totalAmountDonated": 18267,
    "currency": "CAD",
    "lastTransactionAt": "2020-11-07 20:35",
    "lastTransactionAmount": 18267,
    "profile": "https://opencollective.com/hyphacoopinc",
    "name": "Hypha Worker Co-operative Inc.",
    "company": null,
    "description": "A non-share capital worker co-operative incorporated under the Ontario Co-operative Corporations Act.",
    "image": "https://opencollective-production.s3.us-west-1.amazonaws.com/edd7f3d0-9c24-11ea-a9b6-d57e352ad76d.png",
    "email": null,
    "twitter": "https://twitter.com/hyphacoop",
    "github": "https://github.com/hyphacoop",
    "website": "https://hypha.coop"
  },
  {
    "MemberId": 138914,
    "createdAt": "2020-11-07 20:35",
    "type": "ORGANIZATION",
    "role": "BACKER",
    "isActive": true,
    "totalAmountDonated": 18267,
    "lastTransactionAt": "2020-11-25 05:02",
    "lastTransactionAmount": 0,
    "profile": "https://opencollective.com/hyphacoopinc",
    "name": "Hypha Worker Co-operative Inc.",
    "company": null,
    "description": "A non-share capital worker co-operative incorporated under the Ontario Co-operative Corporations Act.",
    "image": "https://opencollective-production.s3.us-west-1.amazonaws.com/edd7f3d0-9c24-11ea-a9b6-d57e352ad76d.png",
    "email": null,
    "twitter": "https://twitter.com/hyphacoop",
    "github": "https://github.com/hyphacoop",
    "website": "https://hypha.coop"
  },
  {
    "MemberId": 140987,
    "createdAt": "2020-11-16 16:39",
    "type": "USER",
    "role": "BACKER",
    "tier": "backer",
    "isActive": true,
    "totalAmountDonated": 5,
    "currency": "CAD",
    "lastTransactionAt": "2020-11-16 16:39",
    "lastTransactionAmount": 5,
    "profile": "https://opencollective.com/bmann",
    "name": "Boris Mann",
    "company": null,
    "description": "Vancouver. Startups. Open Source. Blockchain. Decentralization. Food!",
    "image": "https://www.gravatar.com/avatar/725e3e8f63148459cdbb84f4d673d0ad?default=404",
    "email": null,
    "twitter": "https://twitter.com/bmann",
    "github": "https://github.com/bmann",
    "website": "https://bmannconsulting.com"
  }
]
benhylau commented 3 years ago

How is this API? https://github.com/hyphacoop/api.distributed.press

http://localhost:3000/v0/monetization/oc/compost

{
  "balance": 1827105,
  "currency": "CAD",
  "error": "",
  "errorCode": ""
}

http://localhost:3000/v0/monetization/eth/compost

{
  "balance": "0",
  "currency": "ETH",
  "error": "",
  "errorCode": ""
}
benhylau commented 3 years ago

Thinking more about this, I think the API <action> should be balances, like http://localhost:3000/v0/monetization/balances/compost

{
  "balances": [
    {
      "name": "gitcoin",
      "type": "eth",
      "balance": "0",
      "currency": "ETH"
    },
    {
      "name": "gitcoin",
      "type": "eth",
      "balance": "0",
      "currency": "DAI"
    },
    {
      "name": "open-collective",
      "type": "oc",
      "balance": 1827105,
      "currency": "CAD"
    }
  ],
  "error": "",
  "errorCode": ""
}

What appears on the list should be via configuration, and the names are custom per project, and the types are the selected set that we support. Note that we are using in-message errors bc some of these text are returned via ipfs:// and hyper:// so HTTP errors are not guaranteed.

bennlich commented 3 years ago

Note that we are using in-message errors bc some of these text are returned via ipfs:// and hyper:// so HTTP errors are not guaranteed.

Interesting. So in the ipfs/hyperdrive case, "making an API call" is actually "reading the latest version of a file that we periodically write to"?

benhylau commented 3 years ago

It will have to be ipns:// and hyper:// but yes, and only for GET requests not POSTs. Here is something I wrote before for additional context:

The Monetization API itself is expected to be "read-only" (i.e. GETs). If the publication is supported via Open Collective, the magazine can query real-time balances using its Monetization API (e.g. https://github.com/hyphacoop/distributed-press-organizing/issues/15#issuecomment-733467263). Doesn't this tie the publication to its Distributed Press instance? And why not directly call the Open Collective API? That's because the content may be viewed over ipfs:// and hyper://, and our intention is to serve our APIs over these schemes as well, so it wouldn't tie the publication to our servers since the DWeb keys are portable.

This section came from a larger text relating to our Social APIs https://docs.google.com/document/d/1w4dSt_xCppZVlDt-EL0_V0TbDvhVwKMQ7Us6ogfG02Y/edit# that is out-of-scope for the current iteration.

benhylau commented 3 years ago

Hey @bennlich can I leave the last item to you?

Build web page that fetches from the JS server

Seems duplicate if I do this as well when the API is alrdy up and running and you'll have to build a page anyways.

https://api.distributed.press/compost/v0/monetization/balances will return:

{
  "result": [
    {
      "name": "open-collective",
      "type": "oc",
      "balances": [
        {
          "balance": "1827105",
          "precision": 2,
          "currency": "CAD"
        }
      ]
    },
    {
      "name": "gitcoin",
      "type": "eth",
      "balances": [
        {
          "balance": "0",
          "precision": 6,
          "currency": "ETH"
        }
      ]
    },
    {
      "name": "gitcoin-erc20",
      "type": "erc20",
      "balances": [
        {
          "balance": "11065339",
          "precision": 6,
          "currency": "DAI"
        },
        {
          "balance": "1565339",
          "precision": 6,
          "currency": "CLR7"
        }
      ]
    }
  ],
  "error": "",
  "errorCode": 0
}
bennlich commented 3 years ago

Yep. Sounds good.

benhylau commented 3 years ago

Here is a nice way of getting payment information via a proxy payment pointer. The only issue for us is that the payment pointer becomes tied to our Distributed Press instance, assuming that's the infra running the proxy.

Also related this thread.