{"id":18245098,"url":"https://github.com/edgeapp/airbitz-workshop","last_synced_at":"2025-07-29T02:07:25.379Z","repository":{"id":76839548,"uuid":"94851840","full_name":"EdgeApp/airbitz-workshop","owner":"EdgeApp","description":"A demo app for working with the Airbitz api","archived":false,"fork":false,"pushed_at":"2017-06-20T06:31:00.000Z","size":36,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-21T08:13:31.581Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/EdgeApp.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-20T05:08:02.000Z","updated_at":"2021-05-28T02:50:54.000Z","dependencies_parsed_at":"2024-03-24T06:15:13.472Z","dependency_job_id":null,"html_url":"https://github.com/EdgeApp/airbitz-workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/EdgeApp/airbitz-workshop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgeApp%2Fairbitz-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgeApp%2Fairbitz-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgeApp%2Fairbitz-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgeApp%2Fairbitz-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EdgeApp","download_url":"https://codeload.github.com/EdgeApp/airbitz-workshop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgeApp%2Fairbitz-workshop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267617643,"owners_count":24116208,"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","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-11-05T09:18:52.442Z","updated_at":"2025-07-29T02:07:25.355Z","avatar_url":"https://github.com/EdgeApp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Airbitz Workshop\n\nThe purpose of this workshop is to create a simple node.js application that use the Airbitz library to send and receive money.\n\nThis git repository contains the starting template for the application. The app itself will run entirely in node.js, but there is an express.js server instance for sending information to the browser. This browser doesn't do anything; it's basically just a glorified `console.log` that can happen to display QR codes as well as text.\n\nHere are the steps to get started:\n\n```shell\ngit clone git@github.com:Airbitz/airbitz-workshop.git\ncd airbitz-workshop\nnpm install\n```\n\nOnce that's done, you can use `npm start` to launch the app. You can visit [http://localhost:3000](http://localhost:3000) to see the status page, and you can use ctrl+C to stop the app.\n\n## Logging in to Airbitz\n\nFirst, we need to add the Airbitz library as a dependency:\n\n```shell\nnpm install airbitz-core-js\nnpm install airbitz-io-node-js\n```\n\nNow that that's done, go into `index.js`, and add the following code:\n\n```javascript\n// At the top of the file:\nconst { makeNodeContext } = require('airbitz-io-node-js')\n\n// In the `main` function:\nconst context = makeNodeContext({\n  apiKey: '9c05067d2a349a67b10f3d3fa7d7834d3667a534'\n})\n```\n\nThis will create an Airbitz context object. The context object has a `loginWithPassword` method, which you can use to download your keys from the Airbitz encrypted backup service:\n\n```javascript\n\nreturn context.loginWithPassword('username', 'password').then(function (account) {\n  // Use your account here\n})\n```\n\nYou can find documetation for all these functions and objects at [the Airbitz developer site](https://developer.airbitz.co/javascript/#loginwithpassword).\n\n## Displaying Private Keys\n\nBitcoin private keys control access to the currency. While anybody can *view* the transactions on the bitcoin network, only somebody with the correct private key can *move* money.\n\nPrivate keys are sensitive information, so normally we do everything we can to keep them secret. In this exercise, however, we can going to peek behind the curtain and take a look at some keys. Once the workshop is over, you may want to archive the wallets in your Airbitz account and create some fresh ones.\n\nThe `account.allKeys` parameter contains an array of all the wallet keys in the account, along with their type and metadata.\n\nTo put this list of keys on screen, we first need to convert it into text, and then insert the text into the status web page. We use the standard Javascript `JSON.stringify` function to convert the data to text. The status web page reads its values from a global variable called `output`. Whatever text we put into `output.keys` will appear on the page the next time it is refreshed.\n\nPut together, the code to do this is actually pretty short:\n\n```\noutput.keys = JSON.stringify(account.allKeys, null, 2)\n```\n\nWhile Airbitz has many keys for different purposes, for this exercise, we are interested in the `wallet:bitcoin` type keys.\n\n## Starting the wallet\n\nThe core Airbitz library only provides login functionality. To do transactions, we need to bring in a plugin:\n\n```shell\nnpm install https://github.com/Airbitz/airbitz-currency-bitcoin.git\n```\n\nImport the Javascript:\n\n```javascript\n// At the top of the file:\nconst { makeCurrencyWallet } = require('airbitz-core-js')\nconst { makeBitcoinPlugin } = require('airbitz-currency-bitcoin')\n\n// In the `main` function:\nconst plugin = makeBitcoinPlugin({ io: context.io })\n```\n\nWith that set up, we have what we need to create a wallet:\n\n```javascript\nconst key = account.getFirstWallet('wallet:bitcoin')\nreturn makeCurrencyWallet(key, {\n  io: context.io,\n  plugin,\n  callbacks: { /* todo */ }\n}).then(function (wallet) {\n  return wallet.startEngine().then(function () {\n    // Stash the wallet for later:\n    global.wallet = wallet\n\n    // Use your wallet here\n  })\n})\n```\n\nWe stash the `wallet` as a global variable. We will use it later when we go to do a spend.\n\n## Showing an address\n\nBitcoin wallets can contain multiple addresses. To grab an address out of the wallet, we use the `getReceiveAddress` function:\n\n```javascript\nwallet.getReceiveAddress().then(function (address) {\n  output.address = JSON.stringify(address, null, 2)\n  output.addressSvg = qr.imageSync(address.publicAddress, { type: 'svg' })\n})\n```\n\n## Showing the balance\n\nAs funds arrive in the wallet, the balance will change. Therefore, we need to set up a callback function that can keep the balance up to date as funds arrive:\n\n```\n// Before the wallet is created:\nfunction onBalanceChanged (balance) {\n  output.balance = balance\n}\n\n// Update `makeCurrencyWallet` like so:\nreturn makeCurrencyWallet(key, {\n  io: context.io,\n  plugin,\n  callbacks: { onBalanceChanged }\n})\n```\n\nBy passing this function into the `callbacks` parameter of `makeCurrenyWallet`, it will automatically run when funds arrive. We also need to check the balance once when the app first loads:\n\n```javascript\noutput.balance = wallet.getBalance()\n```\n\n## Receiving money\n\nAt this point, your application has everything it needs to receive money. It is showing a QR code, and is tracking a balance. Please call over one of the Airbitz staff, and we will send you some test funds for the next step.\n\n## Spending money\n\nWithin the application template, there is a `/spend` endpoint that is triggered whenver the user hits the `submit` button on the send form. This is where we are going to put our spend code.\n\nHere is how that looks:\n\n```javascript\nconst spendInfo = {\n  spendTargets: [\n    {\n      publicAddress: req.body.address,\n      amountSatoshi: parseInt(req.body.amount)\n    }\n  ]\n}\n\nglobal.wallet.makeSpend(spendInfo)\n```\n\nThe `spendInfo` structure contains an array of addresses to send money to, called `spendTargets`. In this case, we are putting in the single address the user provided in the form. The `makeSpend` function accepts this information and accomplishes the spend.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedgeapp%2Fairbitz-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedgeapp%2Fairbitz-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedgeapp%2Fairbitz-workshop/lists"}