{"_id":"@daisypayments/daisy-sdk","_rev":"20-7985a5c2a87f4254f10de2c5994b18a3","name":"@daisypayments/daisy-sdk","dist-tags":{"latest":"0.11.1","beta":"0.8.0-beta.4"},"versions":{"0.5.2":{"name":"@daisypayments/daisy-sdk","version":"0.5.2","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","jsdoc:deploy":"gh-pages --add CNAME -d docs","jsdoc":"jsdoc -c jsdoc.conf.js","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"axios":"^0.18.0","eth-sig-util":"^2.1.2","eventemitter3":"^3.1.2"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.4.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4","@babel/preset-env":"^7.4.4","@daisypayments/eslint-config":"^1.6.3","eslint":"^5.16.0","gh-pages":"^2.0.1","husky":"^2.4.1","jest":"^24.7.1","jsdoc":"^3.6.2","rollup":"^1.11.0","rollup-plugin-babel":"^4.3.2","rollup-plugin-commonjs":"^9.3.4","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^4.2.3"},"gitHead":"3ad5f99402fc14628219a745448e15b01ce848b0","description":"## Install","_id":"@daisypayments/daisy-sdk@0.5.2","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-kEvdAkB1mKDrz3l/AafAJpWf8lFedhBFlNTcwhlhvTvAYVmR5iAMpIGpA04DKFELrcGsXV0kxuVPJjW3Hr/fCg==","shasum":"de68d4be908c7c35b692b6504edc1f710f0ba62a","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.5.2.tgz","fileCount":15,"unpackedSize":248126,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdHNtdCRA9TVsSAnZWagAAiTMP/iyu5xmLDSs7h16bwG+H\n60XR7JsIdU2G7NlLjL5op8YlJukkLGPWE4zYJ6UUOe4vlQvxlTE7bTarXl8d\nMqgelkHjkg1nnBME5TdDg/WEliiptZTGNy4TOfrJteRCOjDEUe7842LXG4SP\nHx7y+KVHuXR1g5wbkUqFUMeAM6yQxJbrMqTYVhrScyvJunTC/1MpocsZCi2X\nAUepkL5+5oDnILJf5JAnpoUkObmobTKCcImvgQ6REf0W+/jjegBjbCHzrJEs\n5/X7Te+sfXbZqx6N3h9H3Zu787ldL6KcJa1ThPkICZ0CINkjFfKPY7Cb7CZS\ntSALcErcdbZiuRzCJWiRyT3Ny4iV3nCLlNovC5augN4LA749qa1WR4gmhQxa\n5uEKXvyDksIp/zsNxAqdLWg+I04lxNqCjtbrcpv5bxHHR3Gc5rdu/i64avUg\nybyF0MfRRDIl+13B6SniLXFHexON0ZswqFbvu6QyNhJ9/rNmMiioqcWgsocN\nr1KWVxaGl8cv8QoEzXPVB9Z5WLNBYVoNG+XlE1VeZCpsP8oF1Ryk49hg5IUd\nXg1GuLZL9y/ZqklxSIqY63IkuYQ9zKnrcbOh9qYzBzbdPhNJ0sHXUPqOD4SB\nfQHRJE74CP/KlCcgcQ3PPLUPCwKgRaAtX5iH8fVxhJbr0hueZhSqaGABuZ0U\nJ2ON\r\n=jpUm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQVtgVITrNTQfYjM5BbuDtigZ8ug0zMzt0KBKm20RTXwIgS8G7guQVmsSUM322mkcC9o5MFxIxIgAUyB6TcELCmMQ="}]},"maintainers":[{"name":"sloreti","email":"lhloreti@gmail.com"},{"name":"daisy-duck","email":"hello@daisypayments.com"},{"name":"jmoreira","email":"jmoreiras@gmail.com"}],"_npmUser":{"name":"sloreti","email":"lhloreti@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.5.2_1562172252865_0.1370706705450504"},"_hasShrinkwrap":false},"0.6.0":{"name":"@daisypayments/daisy-sdk","version":"0.6.0","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","jsdoc:deploy":"gh-pages --add CNAME -d docs","jsdoc":"jsdoc -c jsdoc.conf.js","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"axios":"^0.18.0","eth-sig-util":"^2.1.2","eventemitter3":"^3.1.2"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.4.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4","@babel/preset-env":"^7.4.4","@daisypayments/eslint-config":"^1.6.3","eslint":"^5.16.0","gh-pages":"^2.0.1","husky":"^2.4.1","jest":"^24.7.1","jsdoc":"^3.6.2","rollup":"^1.11.0","rollup-plugin-babel":"^4.3.2","rollup-plugin-commonjs":"^9.3.4","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^4.2.3"},"gitHead":"0b1d21d1ea11df1db1cb0dc224b8d7b16e3b2237","description":"## Install","_id":"@daisypayments/daisy-sdk@0.6.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-s76VWeH8d2EuFLIfb9Q1NHPtf7zsO8T0xxMQnEe5YGTZbASju2S/CBQmg8mCE99lZILBYyrdkntcIP8KBe2lmw==","shasum":"0a08eff6f1d7f330e9cd314eacb7cacefd31e895","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.6.0.tgz","fileCount":15,"unpackedSize":225006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdMIfYCRA9TVsSAnZWagAAb1wP/2MlTu7R9Rl4vZ5I0dMM\nnt7Z3qtkc6RbycWjLt9CSd2xmWz/oN5vTH2oK9VFRY6o+nSyax31W0a2IAV8\nP8O1Y6JwTdTJATPgUD1CdNT/sYVkpg0hMnk45godb4psy9lHgG9Tw3IQ3zVf\nHMxcIfvGvJxNtlWrApyPoC61rwg5+AR2Wqi5sWvYkGE/byuoTHZ1AxkC9fKp\nYw235WBSTQAPpitS2N8v+qPR6c11XmdZCWD88Wnl4XSqiOEGGwqt79cZQxDw\nv02fz3GbH7BGrGLSGUVh/oyDc761MYO9rBsS5r6luOS3Y0tWsjHC/pkdaj9U\nXMkGaUjchSnysz+LYJCT4rXVr+xhtnfSqM22sNXvqWTPdrecSN/Yce61Xp3m\neykzH2FF6TVSeANv8TYChPKAKK9f8cbQ65n0bPmFpn7NqebtZvMB3f1oGWDP\nurTrCSUjuvBdFzKIBxv6r5R+JOdJIQUdqOyF2r9oWDjbR08y8NTcyouxnm3L\nNv1q0CQQ2z6xeBqTJXcmXO84cnyaDgPZQd6/eL9EJG9U317Ck8svja3jLFmY\nRNqr7Ep0xMthrSOv5/QzqP3uN5VyHxYOtMmWjFI9UUHcaAeuIQvw/E4EPJfp\nIvdHH6+yn55LoIQjdirorHYrdyqYw+XqkrlAroQ9noDP8P0TNDjrHe7lTZoI\nIHYw\r\n=a8vr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAJzlAXyjcMUxN/VUZ3fXwCD7E8LOVeXfS8JSUR0+dexAiEA1TpyND56eqDO79g4BcEIrdj2PwwWgM8qveAeFNEjYL4="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.6.0_1563461591205_0.5480208629130463"},"_hasShrinkwrap":false},"0.6.1":{"name":"@daisypayments/daisy-sdk","version":"0.6.1","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","jsdoc:deploy":"gh-pages --add CNAME -d docs","jsdoc":"jsdoc -c jsdoc.conf.js","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"axios":"^0.18.0","eth-sig-util":"^2.1.2","eventemitter3":"^3.1.2"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.4.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4","@babel/preset-env":"^7.4.4","@daisypayments/eslint-config":"^1.6.3","eslint":"^5.16.0","gh-pages":"^2.0.1","husky":"^2.4.1","jest":"^24.7.1","jsdoc":"^3.6.2","rollup":"^1.11.0","rollup-plugin-babel":"^4.3.2","rollup-plugin-commonjs":"^9.3.4","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^4.2.3"},"gitHead":"9ad2b991d2a7b8fed8c1897d08162c2c04d3d74e","description":"## Install","_id":"@daisypayments/daisy-sdk@0.6.1","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-KVP3yzhTRtu3DRY6aD/3OGpNNmw6chaaybpqCR13XvWkdn3iOtnQjc5/PFN/zsqNKzKURXggIUMYBW2FkT9uUQ==","shasum":"94d0fa12c42dc0041fdd39940e63891fbfa856c5","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.6.1.tgz","fileCount":16,"unpackedSize":228658,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOcQyCRA9TVsSAnZWagAAWYQP/ijNxYoNihLm8Eam1ikt\nikXjDFNtyMcnUKBUUbxnPKS43Qx1yfofK1wWvooQbCs9K8YaaCxfKJQ0MfNh\nTSdhuQFk9n0qMKnug07S5X92LY+8D5L3eah0GMgNGha1lHKmkcWVONGFKPW+\nDNrZ4hZ4yvattA8i2BXT0zkizST2ClWnrBuRa7xqLAhrcHH8K5KrH8c67+J2\nrhzMoc3dYQsSc33B9cBGwqEER9N1SC7gunV5/UrzD9zGFKgKjhtd+cZvK22F\nLSwAvsTM6wiwrl26XOlSza8gcwX/yZMijMNFbT/bpdxWnqovbjXDf+CF6/3d\nbjInX8BXiF9UYUL7OBABrHNwtuNZtRh2IKH6MfvGR7yVr0GPeHyvX6KqcChX\ncnGrCQGHxLcPOF4s0THQnwxZrfuvtuqhIMo7xYqi9IALJsOE4jSKHhkX1UXt\n/bs1zSLT2XX/Glojxv2meaUA5fQ0yiXKAWiRiAaU5wCB8XkpHgzZVka9/SYC\nQRKb2KJaFTaAAcOhklmrR0D9qk9mewNGjTukhw+IZ3L7TuqU800tAAOgqxOR\nwEaCEgzdw1xulPCjo6+KtqzK/l7B+kc2RmqIux/xzitPCzL2khzjXJUkPgF6\nFkj92tDQ07qa2a3b/FP5c+k42ihF1cUruW+71D1nphCw6CvonwhTM4BBBF9j\ne6MF\r\n=Hlkr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDV2mLCJwdZLoibKxx1eCZXUqiG7uTSMl9nwdCh0saZpAiEA+cB3zIIvMJMyDBsqTMc0m4jDShBii6Vd0jhsaV0+OAs="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.6.1_1564066865799_0.46992024889955575"},"_hasShrinkwrap":false},"0.7.0":{"name":"@daisypayments/daisy-sdk","version":"0.7.0","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","jsdoc:deploy":"gh-pages --add CNAME -d docs","jsdoc":"jsdoc -c jsdoc.conf.js","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"axios":"^0.18.0","eth-sig-util":"^2.1.2","eventemitter3":"^3.1.2"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.4.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4","@babel/preset-env":"^7.4.4","@daisypayments/eslint-config":"^1.6.3","eslint":"^5.16.0","gh-pages":"^2.0.1","husky":"^2.4.1","jest":"^24.7.1","jsdoc":"^3.6.2","rollup":"^1.11.0","rollup-plugin-babel":"^4.3.2","rollup-plugin-commonjs":"^9.3.4","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^4.2.3"},"gitHead":"6a44cb7f256dbb0d0117ae81360223c3f83ae9f4","description":"## Install","_id":"@daisypayments/daisy-sdk@0.7.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-jr8o7BnU2a0oKUJwd0UQVJ8i/9cKqS66qNIYCU/pJCaTqwkhsONuzbyon8OJAs87RnmKAbIrtdCVFqwL2L0vbQ==","shasum":"c8145d9a911407413245b82331de70e9649a53ea","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.7.0.tgz","fileCount":16,"unpackedSize":229082,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdXrUQCRA9TVsSAnZWagAAHsIP/jKTxEvkYTPHlL4fPEeb\nsID1xgTRdxytJS3C342nz59Bl2JpnhZUo/PQLRek5h3PyytrejRUfxV53yne\n8AA7b5YLyfk9hnP0pldBAVkGw9NwdAPWCT1JzgmCr91Obrt2iEkREaZe4vyk\nG1Ght0pgnkCHV5WIyHdN8glBe0F1PGNWOESTEpXV5lMgBTVMY9XDWhPyhFm+\nX5RXSdpqhiLSLQdTAw34Gv2bM21buQS1O4L2pvdpLD2qOnsl0VC76gtUO3hj\nwYFxeq9XWX9CmZ8F6+PFbKOFwj6MWSjnyYNRLoLGTmZ+7g+vRAO5q0ss4Pnk\naCib8QvwyQ7LY2NZyJCoKC5oKSsOheqGGY4lxlft5Tp7z2GN8JUTJoKM6Fb5\n6i8LVxx3BYpwT6oGMwy2OhKR73m3XWVmbycZ2NDwohQQAMlm45r2Q3PKA+es\nnOB/1Kw6FLHbt0toctwJngHxEkp+WYbY6B5g/KSOSQtb3mN4NESpC5YAOS+a\ncmK6jGIaCtZnf2+fA8aUGdwNWSkf1sv7h3+Wa4/GJ+1PxdAq3bklMIAHBbBI\nnVbPoHkAgSHwfi1tyTrQmcnPbuZNLVpemm1/cRBEcoPGtQuVNETX4fA5hNtm\nqh0PcM+s6kgk07hCfYvM0ECTPd270FVJPQcM3TAZ3d6RFEwbtwGp1VtxiPax\nZulr\r\n=+SL9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjSPIM1rEoaeNtSGT5vEywCfqIBQFUH5f4KUtaQsoIcwIgP8qxeVL3FNjQoGFcrj2Y3Zncqx1gOfnNHAog7F2Dvkw="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.7.0_1566487824102_0.27264688360451905"},"_hasShrinkwrap":false},"0.7.0-beta.1":{"name":"@daisypayments/daisy-sdk","version":"0.7.0-beta.1","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","axios":"^0.18.0","eth-sig-util":"^2.1.2","eventemitter3":"^3.1.2"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.4.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4","@babel/preset-env":"^7.4.4","@daisypayments/eslint-config":"^1.6.3","eslint":"^5.16.0","husky":"^2.4.1","jest":"^24.7.1","rollup":"^1.11.0","rollup-plugin-babel":"^4.3.2","rollup-plugin-commonjs":"^9.3.4","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^4.2.3"},"readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `axios`, `web3`, `eventemitter3`, and `querystring`.\n\n```nocode\nyarn add @daisypayments/daisy-sdk axios eventemitter3 querystring web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/daisypayments/react-metamask#readme).\n\n## Usage\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and get the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServiceSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServiceSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\n\nconst subscriptionService = new ServiceSubscriptions({\n  identifier: process.env.DAISY_ID,\n  secretKey: process.env.DAISY_SECRET_KEY,\n});\n```\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptionService.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptionService.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw // ...\n  }\n\n  let authSignature = null; // not required for public plans.\n  if (plan.private) {\n    // TODO: Add conditions for `user` to use private plan.\n\n    const authorizer = {\n      privateKey: Buffer.from(process.env.PRIVATE_KEYS, \"hex\"),\n    };\n    authSignature = await subscriptionService.authorize(\n      authorizer,\n      agreement,\n    );\n  }\n\n  const { data: subscription } = await subscriptionService.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\nawait daisy.sync();\n\nconst token = daisy.loadToken(); // web3.js contract instance\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .prepareToken(token)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\nawait daisy.sync();\n\nconst token = daisy.loadToken(); // web3.js contract instance\n\nconst { signature, agreement } = await daisy\n  .prepareToken(token)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst subscription = await subscriptionService.getSubscription({\n  id: daisyID,\n});\nconsole.log(subscription[\"state\"]);\n\nconst subscriptions = await subscriptionService.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\nDaisy Invitation allows client to externalize the flow to Daisy's domain.\n\n#### 2.1 Recommended usage: WebHooks\n\nLet's say you created a Daisy Invitation with the following id:\n\n```txt\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: {}\n\n```\n\nThen we need to route `callbackURL` to your server URL (with HTTPS) and a path.\nThis route must handle a HTTP POST request and return a `2XX` status code.\n\n```ts\n// TypeScript typing\n\ntype ID = string;\n\n/**\n * JSON Payload attached to the POST request to `callbackURL`\n */\ninterface WebhookFromInvitation {\n  /**\n   * Semver string\n   * Current version: 1.0.0\n   */\n  version: string;\n  subscription: {\n    /**\n     * DaisyID\n     */\n    daisyId: ID;\n  };\n  plan: {\n    id: ID;\n    private: boolean;\n  };\n  invitation: {\n    id: ID;\n    automatic: boolean;\n  };\n  agreement: CreateSubscriptionAgreement;\n  /**\n   * When pre-signed (maybe because automatic was set to `true`) this field contains the authorizer signature.\n   * To void a pre-signed subscription, return `{ authSignature: null }` from the webhook.\n   */\n  authSignature: string | null;\n  extra: any;\n  /**\n   * Use SDK to verify this signature.\n   */\n  digest: string;\n}\n\ninterface CreateSubscriptionAgreement {\n  subscription: SubscriptionAgreement;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  previousSubscriptionId: string;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  credits: string;\n  nonce: string;\n  signatureExpiresAt: string;\n};\n\ninterface SubscriptionAgreement {\n  /**\n   * Ethereum address (subscriber)\n   */\n  subscriber: string;\n  /**\n   * Ethereum address (ERC20 Token)\n   */\n  token: string;\n  price: string;\n  /**\n   * DAY | MONTH | YEAR\n   */\n  periodUnit: string;\n  /**\n   * Number as string (blockchain stuff)\n   */\n  periods: string;\n  maxExecutions: string; // 0 = infinite\n  /**\n   * Plan's onChainId\n   */\n  plan: string;\n}\n```\n\nSo a normal server should handle this POST request like:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  // TODO: Identify the user\n  await user.patch({ daisyID: subscription[\"daisyId\"] });\n\n  // Optional redirect URL, may have custom tokens.\n  // Is not guaranteed the user is going to enter this URL.\n  const redirectURL = \"https://myapp.com/checkount/finish/\";\n\n  res.json({ authSignature, redirectURL })\n}));\n```\n\n#### 2.2 Voiding a subscription\n\nTo void a subscription and prevent the blockchain transaction set `authSignature` to `null`.\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  /* Void logic */\n\n  res.json({ authSignature: null });\n}));\n```\n\n#### 2.3 Identifying the user\n\nOne way to identify an user after getting the callback is by knowing before-hand the user's Ethereum address.\nSo it can be queried from `req.body[\"agreement\"][\"subscriber\"]`\n\nA better way is setting the `callbackExtra` payload to something we can recognize in the backend.\nExample:\n\n```language\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: { \"email\": \"user@daisypayments.com\" }\n```\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, extra } = req.body\n\n  // TODO: Identify the user\n  await user.findById({ email: extra[\"email\"] }).patch({ daisyId: subscription[\"daisyId\"] });\n\n  // ...\n\n  const redirectURL = `https://myapp.com/checkount/finish/?user=${user.id}`;\n\n  res.json({ authSignature, redirectURL })\n}\n```\n\n#### 2.4 Verify authenticity\n\nTo tell if the webhook POST actually came from Daisy servers you can verify its signature:\n\n```js\nconst { verify } = require('@daisypayments/daisy-sdk/private/webhooks');\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { digest, ...payload } = req.body\n\n  const isAuthentic = verify({\n    message: payload,\n    digest: digest,\n    publicKey: process.env.DAISY_CALLBACK_PUBLIC_KEY,\n  });\n\n  if (!isAuthentic) {\n    // ...\n    res.json({ authSignature: null });\n  }\n\n  // ...\n});\n```\n","readmeFilename":"README.md","gitHead":"c6f481d684efa9f4d82fa78ec24c0e086d87a340","description":"## Install","_id":"@daisypayments/daisy-sdk@0.7.0-beta.1","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-ibwqsfmkLEuAslW17p46GJlBJbn5ZipBzcZuz5piZKHxcC4OGnSIKlJveRimnBfc3HRJu7LSaiEUX0B8/hf67w==","shasum":"c964e1e202e0f8cffe29cc4270b956d8fe990d23","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.7.0-beta.1.tgz","fileCount":16,"unpackedSize":242396,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdhROaCRA9TVsSAnZWagAAtQ0P/RstR3oJPfh/gXat7n0I\nvWU4JZSBOr7YBq1iuU1sDCLimOKoTUxCjrPPfXI2Hi+fyZ40j9SU2XAvN0zx\n0z6T9G3Rf+dUd1cGA3bGzk44Z+aqkaW4at22acaISis/31jQlF3a0Y3HoPiS\nUo/SwDv5wxGNgdrcxQhHjDReJUZdN96U1jFV9AVeMf2vXTX0VLjdu2qLspSP\nJwLjvBc5D/BRprZAcAhR8ppYkVnEw+P3zaK24iS7DeJd2oFeNj975jOBsDty\nURRoJOZv5vL/nFAtZfzDkv+EUmpv+MPkZVT1kN4lmGwd7F3j4ApLiOVSwCIC\nOC4YFuAnf+EBPst4Oz3KucnYgInRnYxuXUTicahFj5uQ7uSgQsnsiPsOEfGP\nMoWWs9qhPxlV4N7ChABfR7QVLhDvkeZ+W5h5fZ/rZfnPHbVWOErrMJXSwk/l\nYK/Z+frTMWo4fbqTynZy32BWKBRQ064pXRY6naCkZlZfSeaA7VqjAT65Eh2V\nLapTUCBumR7ic8ypmpa029ZxVggIOhvq0INrSX7yhIXaBVudJ6SIYLUDQYN8\nTZ4dBgfrBMClJqgmKIpCtwcbosFfXvQcVIQmrdnXdMO/OPg/A8uqQ2oLT9Fp\nv3sEnEDErefmzV6/xDyapDQN7giLedU9oueaUq/AzY2Fgg07IW2NgbHEMJ5p\n5gwa\r\n=70I4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMtErh7tUxZnroC153Bnx/5Ok+giNihF0W8HWEF0iZiwIgOqa7Jhcmrw5dWwekOr4Qom2rY9WyzNBOUY8Pu8WoQ7g="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.7.0-beta.1_1569002393745_0.24434503862157553"},"_hasShrinkwrap":false},"0.7.0-beta.2":{"name":"@daisypayments/daisy-sdk","version":"0.7.0-beta.2","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.0","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.6.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.6.2","@babel/preset-env":"^7.6.3","@daisypayments/eslint-config":"^1.7.0","eslint":"^6.6.0","husky":"^3.0.9","jest":"^24.9.0","rollup":"^1.26.2","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `web3`, and `eventemitter3`\n\n```nocode\nyarn add @daisypayments/daisy-sdk eventemitter3 web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/Consensys/react-metamask).\n\n## Usage\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and get the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServiceSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServiceSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nServiceSubscriptions.fetch = fetch;\nconst subscriptionService = new ServiceSubscriptions({\n  identifier: process.env.DAISY_ID,\n  secretKey: process.env.DAISY_SECRET_KEY,\n});\n```\n\n> Server instances requires an assignation of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptionService.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptionService.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw // ...\n  }\n\n  let authSignature = null; // not required for public plans.\n  if (plan.private) {\n    // TODO: Add conditions for `user` to use private plan.\n\n    const authorizer = {\n      privateKey: Buffer.from(process.env.PRIVATE_KEYS, \"hex\"),\n    };\n    authSignature = await subscriptionService.authorize(\n      authorizer,\n      agreement,\n    );\n  }\n\n  const { data: subscription } = await subscriptionService.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\nawait daisy.sync();\n\nconst token = daisy.loadToken(); // web3.js contract instance\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .prepareToken(token)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\nawait daisy.sync();\n\nconst token = daisy.loadToken(); // web3.js contract instance\n\nconst { signature, agreement } = await daisy\n  .prepareToken(token)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst subscription = await subscriptionService.getSubscription({\n  id: daisyID,\n});\nconsole.log(subscription[\"state\"]);\n\nconst subscriptions = await subscriptionService.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\nDaisy Invitation allows client to externalize the flow to Daisy's domain.\n\n#### 2.1 Recommended usage: WebHooks\n\nLet's say you created a Daisy Invitation with the following id:\n\n```txt\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: {}\n\n```\n\nThen we need to route `callbackURL` to your server URL (with HTTPS) and a path.\nThis route must handle a HTTP POST request and return a `2XX` status code.\n\n```ts\n// TypeScript typing\n\ntype ID = string;\n\n/**\n * JSON Payload attached to the POST request to `callbackURL`\n */\ninterface WebhookFromInvitation {\n  /**\n   * Semver string\n   * Current version: 1.0.0\n   */\n  version: string;\n  subscription: {\n    /**\n     * DaisyID\n     */\n    daisyId: ID;\n  };\n  plan: {\n    id: ID;\n    private: boolean;\n  };\n  invitation: {\n    id: ID;\n    automatic: boolean;\n  };\n  agreement: CreateSubscriptionAgreement;\n  /**\n   * When pre-signed (maybe because automatic was set to `true`) this field contains the authorizer signature.\n   * To void a pre-signed subscription, return `{ authSignature: null }` from the webhook.\n   */\n  authSignature: string | null;\n  extra: any;\n  /**\n   * Use SDK to verify this signature.\n   */\n  digest: string;\n}\n\ninterface CreateSubscriptionAgreement {\n  subscription: SubscriptionAgreement;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  previousSubscriptionId: string;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  credits: string;\n  nonce: string;\n  signatureExpiresAt: string;\n};\n\ninterface SubscriptionAgreement {\n  /**\n   * Ethereum address (subscriber)\n   */\n  subscriber: string;\n  /**\n   * Ethereum address (ERC20 Token)\n   */\n  token: string;\n  price: string;\n  /**\n   * DAY | MONTH | YEAR\n   */\n  periodUnit: string;\n  /**\n   * Number as string (blockchain stuff)\n   */\n  periods: string;\n  maxExecutions: string; // 0 = infinite\n  /**\n   * Plan's onChainId\n   */\n  plan: string;\n}\n```\n\nSo a normal server should handle this POST request like:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  // TODO: Identify the user\n  await user.patch({ daisyID: subscription[\"daisyId\"] });\n\n  // Optional redirect URL, may have custom tokens.\n  // Is not guaranteed the user is going to enter this URL.\n  const redirectURL = \"https://myapp.com/checkount/finish/\";\n\n  res.json({ authSignature, redirectURL })\n}));\n```\n\n#### 2.2 Voiding a subscription\n\nTo void a subscription and prevent the blockchain transaction set `authSignature` to `null`.\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  /* Void logic */\n\n  res.json({ authSignature: null });\n}));\n```\n\n#### 2.3 Identifying the user\n\nOne way to identify an user after getting the callback is by knowing before-hand the user's Ethereum address.\nSo it can be queried from `req.body[\"agreement\"][\"subscriber\"]`\n\nA better way is setting the `callbackExtra` payload to something we can recognize in the backend.\nExample:\n\n```language\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: { \"email\": \"user@daisypayments.com\" }\n```\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, extra } = req.body\n\n  // TODO: Identify the user\n  await user.findById({ email: extra[\"email\"] }).patch({ daisyId: subscription[\"daisyId\"] });\n\n  // ...\n\n  const redirectURL = `https://myapp.com/checkount/finish/?user=${user.id}`;\n\n  res.json({ authSignature, redirectURL })\n}\n```\n\n#### 2.4 Verify authenticity\n\nTo tell if the webhook POST actually came from Daisy servers you can verify its signature:\n\n```js\nconst { verify } = require('@daisypayments/daisy-sdk/private/webhooks');\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { digest, ...payload } = req.body\n\n  const isAuthentic = verify({\n    message: payload,\n    digest: digest,\n    publicKey: process.env.DAISY_CALLBACK_PUBLIC_KEY,\n  });\n\n  if (!isAuthentic) {\n    // ...\n    res.json({ authSignature: null });\n  }\n\n  // ...\n});\n```\n","readmeFilename":"README.md","gitHead":"eaf7ee832ac6fb61fbfb040cdb4d0fd1d02b84ad","description":"## Install","_id":"@daisypayments/daisy-sdk@0.7.0-beta.2","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-zQJtAboVMQvglqIcS3Uu9NOdRcqNjkNR4ZsYP6tgMzUfqge4obb9Jku60WtcrbKCkx5ejZBfwsszh+SGX5Gyew==","shasum":"36ea003a7e40f1fefeb259e1a1a393331e3973cd","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.7.0-beta.2.tgz","fileCount":17,"unpackedSize":287173,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdxI5lCRA9TVsSAnZWagAAmxoP/jYpFaLR9H+0E8QPA/iE\nMfIIUDkB4oyVKSzmB8GTAxkUcVNFaJraZtmrkShD1luVKATHgO4L6letwOK6\nADjcP4YOUnY0WVIxTcaS3bzkb5nmUx4Ygk/wgzI8boKJJjBKhXGq83AbGAoU\numX+6QQwIIHRhqL+oYCk3jE0Qwg77umvTT0Cb0weJjBvcNMInGuburnjfs45\nx0jax7kRlDrQDORVDDQdcEiG5o3pR+8p0sT5szd35padpyvHqvlXWmwQNUR8\nQ8kWZOJWmQ3UV/1dl7uE4zzK9M3UgBC32ByhPebqNjz/ScOMqLm3VTb9ANUQ\nB97ZRRCSZln84lCaO/YUEvKiqMIP3+L9IJngUdYA1P1uH6C7UY9wZ8Fblr58\nAYdtQZ3Dd212Qiztq7KZMSJ9cgiUDgsSYfuE0DuC+9+Uq46F68iZSYEwrsC5\niaCeL6fbPZ5uRFull06NIwEvHOgHw1wJC4tM8unyWJoQJgFoCQm1RmEJ0kjr\nizJYM7JUP0jxeCib2R2pwyM7y/vOLXERoH6cZvI/SHZTWr/c5EcLxwAM7iao\nv8q2uqhhaV1YFbxMXFcU6RLIWEip9npBOZ9CInCholVHhd6qWR+OkFyh67WT\nyb/oZFDcXMdFWnP3FMBE+TTKaheFDTpFmy/zISNryd5/DsC4fgTaG6vrEbAW\n+W2L\r\n=ZTAm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdU8bwnUXVW5RHvXgwIrZQVlX/KbvdZF//vOi+X40aCgIhAJ9sy520OUzB+WgoMoCFv7vbk5YXuYncMrpxpHYvrezE"}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.7.0-beta.2_1573162597272_0.6296617256492514"},"_hasShrinkwrap":false},"0.8.0-beta.1":{"name":"@daisypayments/daisy-sdk","version":"0.8.0-beta.1","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.0","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.6.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.6.2","@babel/preset-env":"^7.6.3","@daisypayments/eslint-config":"^1.7.0","eslint":"^6.6.0","husky":"^3.0.9","jest":"^24.9.0","rollup":"^1.26.2","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `web3`, and `eventemitter3`\n\n```nocode\nyarn add @daisypayments/daisy-sdk eventemitter3 web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/Consensys/react-metamask).\n\n## Usage\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and get the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServiceSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServiceSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nServiceSubscriptions.fetch = fetch;\nconst subscriptionService = new ServiceSubscriptions({\n  identifier: process.env.DAISY_ID,\n  secretKey: process.env.DAISY_SECRET_KEY,\n});\n```\n\n> Server instances requires an assignation of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptionService.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptionService.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw // ...\n  }\n\n  let authSignature = null; // not required for public plans.\n  if (plan.private) {\n    // TODO: Add conditions for `user` to use private plan.\n\n    const authorizer = {\n      privateKey: Buffer.from(process.env.PRIVATE_KEYS, \"hex\"),\n    };\n    authSignature = await subscriptionService.authorize(\n      authorizer,\n      agreement,\n    );\n  }\n\n  const { data: subscription } = await subscriptionService.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\nawait daisy.sync();\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .prepareToken(token)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = new DaisySDK({ identifier: \"margarita\" }, web3)\nawait daisy.sync();\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst { signature, agreement } = await daisy\n  .prepareToken(token)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst subscription = await subscriptionService.getSubscription({\n  id: daisyID,\n});\nconsole.log(subscription[\"state\"]);\n\nconst subscriptions = await subscriptionService.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\nDaisy Invitation allows client to externalize the flow to Daisy's domain.\n\n#### 2.1 Recommended usage: WebHooks\n\nLet's say you created a Daisy Invitation with the following id:\n\n```txt\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: {}\n\n```\n\nThen we need to route `callbackURL` to your server URL (with HTTPS) and a path.\nThis route must handle a HTTP POST request and return a `2XX` status code.\n\n```ts\n// TypeScript typing\n\ntype ID = string;\n\n/**\n * JSON Payload attached to the POST request to `callbackURL`\n */\ninterface WebhookFromInvitation {\n  /**\n   * Semver string\n   * Current version: 1.0.0\n   */\n  version: string;\n  subscription: {\n    /**\n     * DaisyID\n     */\n    daisyId: ID;\n  };\n  plan: {\n    id: ID;\n    private: boolean;\n  };\n  invitation: {\n    id: ID;\n    automatic: boolean;\n  };\n  agreement: CreateSubscriptionAgreement;\n  /**\n   * When pre-signed (maybe because automatic was set to `true`) this field contains the authorizer signature.\n   * To void a pre-signed subscription, return `{ authSignature: null }` from the webhook.\n   */\n  authSignature: string | null;\n  extra: any;\n  /**\n   * Use SDK to verify this signature.\n   */\n  digest: string;\n}\n\ninterface CreateSubscriptionAgreement {\n  subscription: SubscriptionAgreement;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  previousSubscriptionId: string;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  credits: string;\n  nonce: string;\n  signatureExpiresAt: string;\n};\n\ninterface SubscriptionAgreement {\n  /**\n   * Ethereum address (subscriber)\n   */\n  subscriber: string;\n  /**\n   * Ethereum address (ERC20 Token)\n   */\n  token: string;\n  price: string;\n  /**\n   * DAY | MONTH | YEAR\n   */\n  periodUnit: string;\n  /**\n   * Number as string (blockchain stuff)\n   */\n  periods: string;\n  maxExecutions: string; // 0 = infinite\n  /**\n   * Plan's onChainId\n   */\n  plan: string;\n}\n```\n\nSo a normal server should handle this POST request like:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  // TODO: Identify the user\n  await user.patch({ daisyID: subscription[\"daisyId\"] });\n\n  // Optional redirect URL, may have custom tokens.\n  // Is not guaranteed the user is going to enter this URL.\n  const redirectURL = \"https://myapp.com/checkount/finish/\";\n\n  res.json({ authSignature, redirectURL })\n}));\n```\n\n#### 2.2 Voiding a subscription\n\nTo void a subscription and prevent the blockchain transaction set `authSignature` to `null`.\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  /* Void logic */\n\n  res.json({ authSignature: null });\n}));\n```\n\n#### 2.3 Identifying the user\n\nOne way to identify an user after getting the callback is by knowing before-hand the user's Ethereum address.\nSo it can be queried from `req.body[\"agreement\"][\"subscriber\"]`\n\nA better way is setting the `callbackExtra` payload to something we can recognize in the backend.\nExample:\n\n```language\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: { \"email\": \"user@daisypayments.com\" }\n```\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, extra } = req.body\n\n  // TODO: Identify the user\n  await user.findById({ email: extra[\"email\"] }).patch({ daisyId: subscription[\"daisyId\"] });\n\n  // ...\n\n  const redirectURL = `https://myapp.com/checkount/finish/?user=${user.id}`;\n\n  res.json({ authSignature, redirectURL })\n}\n```\n\n#### 2.4 Verify authenticity\n\nTo tell if the webhook POST actually came from Daisy servers you can verify its signature:\n\n```js\nconst { verify } = require('@daisypayments/daisy-sdk/private/webhooks');\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { digest, ...payload } = req.body\n\n  const isAuthentic = verify({\n    message: payload,\n    digest: digest,\n    publicKey: process.env.DAISY_CALLBACK_PUBLIC_KEY,\n  });\n\n  if (!isAuthentic) {\n    // ...\n    res.json({ authSignature: null });\n  }\n\n  // ...\n});\n```\n","readmeFilename":"README.md","gitHead":"66e50b5c91d9f8ea6f4ad41ca63b809109e012bb","description":"## Install","_id":"@daisypayments/daisy-sdk@0.8.0-beta.1","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-IM9y7sGqjT2HcRHdWRy1dbj6UuL04nQ7RHLa+glLHOGdhnXAuV7GmaKJDmu9rGje3jhD0S2eXfsUhrAh8rla/g==","shasum":"86a2ec659217993ee80b6ef9cc2c33e47cc15cda","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.8.0-beta.1.tgz","fileCount":17,"unpackedSize":286933,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd3q72CRA9TVsSAnZWagAAfFEQAJ9jRk1zEl7GF8co/EZB\nCxOV2jqyVKL724NXT+cVDHzt54jnAaTcGQIZFVk9768PWWi8L7yUHEGUs72z\n4B+F+bcre2i/g0rclTYR7XDitsNVBVCdcfEfXETWJyhvpjhPy28gcO/RKBwg\nOdIDl1wjtmxACkyXpaoT0AcTxPBwsJ99Hw3o4cU8K7kaqmwds3p+ztdMKzj5\nHHvrQso7O90TCcFpdi332yeS0UaMzaWKQzhNbtUfelyzK6F3JOrslUINz+2f\nFTKz+6kgoP+C/vNXKPG7yb4MdwjZbBxeaPIbX1PtIzXDJBCbFwrNmzE3mlKH\nAwN6DNZajaTq+o59yRYfT/4MdpzbW+1VSpPz4+6FIh7AGb2JFRMr6PWAispd\nx+av1jR9M41oNh/CGk6UkRzFEULWopmtB83ZtSIYhWs6vWfRw/EQEVk+GEQM\nT9zbMlojlYvG7UvarVM9thsbzquPgZFtWKUaTaDUP7G69vuv/ffOAoIdblvY\n+3Y08KYfA7dcFi0XMO7a1oRf4YhovujvXRmMa2nLpr6m7/FkLfH7wDHYzJ7h\nQRcszGIP0COVjYS9OZH4iyU1iodGFjzF0g6qie5xAdThCj4zwdqVcoTfFY2/\ndpJ+kuhs+jaFY0ImdiSJ2ieoyUPSYYBbafOcSNpbTb+tWxrDz3p5jgjB2WNi\nVMtx\r\n=c/fT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHJNDHt4kJsaYsf8JlwOR3+gtooH1Jl//kSh/ZZWMS34AiA8+K2rsn9B+kaasdvUL5TRPchZ4zLvk56s2X9HcQCJ0g=="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.8.0-beta.1_1574874869564_0.29286785599647214"},"_hasShrinkwrap":false},"0.8.0-beta.2":{"name":"@daisypayments/daisy-sdk","version":"0.8.0-beta.2","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.0","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.6.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.6.2","@babel/preset-env":"^7.6.3","@daisypayments/eslint-config":"^1.7.0","eslint":"^6.6.0","husky":"^3.0.9","jest":"^24.9.0","rollup":"^1.26.2","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `web3`, and `eventemitter3`\n\n```nocode\nyarn add @daisypayments/daisy-sdk eventemitter3 web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/Consensys/react-metamask).\n\n## Usage: Subscriptions\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServerSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServerSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nServerSubscriptions.fetch = fetch;\nconst subscriptions = new ServerSubscriptions({\n  manager: {\n    identifier: process.env.DAISY_ID,\n    secretKey: process.env.DAISY_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptions.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptions.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw new Error(\"Plan not found\");\n  }\n\n  const { data: subscription } = await subscriptions.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .prepareToken(token)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst { signature, agreement } = await daisy\n  .prepareToken(token)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst sub = await subscriptions.getSubscription({\n  id: daisyID,\n});\nconsole.log(sub[\"state\"]);\n\nconst subs = await subscriptions.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\nDaisy Invitation allows client to externalize the flow to Daisy's domain.\n\n#### 2.1 Recommended usage: WebHooks\n\nLet's say you created a Daisy Invitation with the following:\n\n```txt\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: {}\n\n```\n\nThis route (`callbackURL`) must handle a HTTP POST request and return a `2XX` status code.\n\n```ts\n// TypeScript typing\n\ntype ID = string;\n\n/**\n * JSON Payload attached to the POST request to `callbackURL`\n */\ninterface WebhookFromInvitation {\n  /**\n   * Semver string\n   * Current version: 1.0.0\n   */\n  version: string;\n  subscription: {\n    /**\n     * DaisyID\n     */\n    daisyId: ID;\n  };\n  plan: {\n    id: ID;\n    private: boolean;\n  };\n  invitation: {\n    id: ID;\n    automatic: boolean;\n  };\n  agreement: CreateSubscriptionAgreement;\n  /**\n   * When pre-signed (maybe because automatic was set to `true`) this field contains the authorizer signature.\n   * To void a pre-signed subscription, return `{ authSignature: null }` from the webhook.\n   */\n  authSignature: string | null;\n  extra: any;\n  /**\n   * Use SDK to verify this signature.\n   */\n  digest: string;\n}\n\ninterface CreateSubscriptionAgreement {\n  subscription: SubscriptionAgreement;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  previousSubscriptionId: string;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  credits: string;\n  nonce: string;\n  signatureExpiresAt: string;\n};\n\ninterface SubscriptionAgreement {\n  /**\n   * Ethereum address (subscriber)\n   */\n  subscriber: string;\n  /**\n   * Ethereum address (ERC20 Token)\n   */\n  token: string;\n  price: string;\n  /**\n   * DAY | MONTH | YEAR\n   */\n  periodUnit: string;\n  /**\n   * Number as string (blockchain stuff)\n   */\n  periods: string;\n  maxExecutions: string; // 0 = infinite\n  /**\n   * Plan's onChainId\n   */\n  plan: string;\n}\n```\n\nSo a normal server should handle this POST request like:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  // TODO: Identify the user\n  await user.patch({ daisyID: subscription[\"daisyId\"] });\n\n  // Optional redirect URL, may have custom tokens.\n  // Is not guaranteed the user is going to enter this URL.\n  const redirectURL = \"https://myapp.com/checkount/finish/\";\n\n  res.json({ authSignature, redirectURL })\n}));\n```\n\n#### 2.2 Voiding a subscription\n\nTo void a subscription and prevent the blockchain transaction set `authSignature` to `null`.\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  /* Void logic */\n\n  res.json({ authSignature: null });\n}));\n```\n\n> An alternative way of voiding is to return any response with a 400 or 500 HTTP status code.\n\n#### 2.3 Identifying the user\n\nOne way to identify an user after getting the callback is by knowing before-hand the user's Ethereum address.\nSo it can be queried from `req.body[\"agreement\"][\"subscriber\"]`\n\nA better way is setting the `callbackExtra` payload to something we can recognize in the backend.\nExample:\n\n```language\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: { \"email\": \"user@daisypayments.com\" }\n```\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, extra } = req.body\n\n  // TODO: Identify the user\n  await user.findById({ email: extra[\"email\"] }).patch({ daisyId: subscription[\"daisyId\"] });\n\n  // ...\n\n  const redirectURL = `https://myapp.com/checkount/finish/?user=${user.id}`;\n\n  res.json({ authSignature, redirectURL })\n}\n```\n\n#### 2.4 Verify authenticity\n\nTo tell if the webhook POST actually came from Daisy servers you can verify its signature:\n\n```js\nconst { verify } = require(\"@daisypayments/daisy-sdk/private/webhooks\");\nconst dedent = require(\"dedent\");\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { digest, ...payload } = req.body\n\n  const isAuthentic = verify({\n    message: payload,\n    digest: digest,\n    publicKey: dedent`\n      -----BEGIN PUBLIC KEY-----\n      MYIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyUaW5FK4ogS2/j7e7h65\n      u73/1QrdfocqHB14123kMQO6Z2CR1+dqa9afty3DQ+mLJ7gupOjvYFYrsiIQoMVc\n      J3zsmlYNjAnoHe8Kn2nU+Gjq+mJ6mscRIC6uMIMm/LslsiMugeL1YlpYXZ0uwbnY\n      TDKiC+g08iGc3tNiaFVCrzNcTH3221vasd321vh21UkWPcAJFDSR+YTtrXjpLMAB\n      jm3Vij8IarAmoCmTMIlUPbCb3j6NMjP4r0hulFUx6/u0DFvQPfKwzKnOph0CoX8u\n      kde74DGOsKxinYycP20w73aypC9eLY7M3PKtJCft3EypTEvgZRHG5Wd2BaTOvzF4\n      tQIDAGAB\n      -----END PUBLIC KEY-----\n    `,\n  });\n\n  if (!isAuthentic) {\n    // ...\n    res.json({ authSignature: null });\n  }\n\n  // ...\n});\n```\n\n## Usage: Payments invoices\n\n### 1. Creating invoices with Daisy SDK\n\n#### 1.1 Create an Invitation\n\nThe first step is going to the Daisy Dashboard and setup an Invitation product. After setting this go to the API Integration and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_OTP_ID=plantae\nDAISY_OTP_SECRET_KEY=key\n```\n\n#### 1.2 Server integration\n\nCreate an instance of `ServerPayments` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_OTP_SECRET_KEY` **private**.\n\n```js\nconst DaisySDK = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nconst payments = new DaisySDK.ServerPayments({\n  manager: {\n    identifier: process.env.DAISY_OTP_ID,\n    secretKey: process.env.DAISY_OTP_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nLet's say we want to sell an access pass for 20 USD or equivalent in DAI.\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\napp.get(\"/api/checkout/invoice/\", h(async (req, res) => {\n  const user = req.session;\n\n  // Create an invoice using Daisy SDK\n  const invoice = await payments.createInvoice({\n    invoicedPrice: 20, // required\n    invoicedEmail: user.email, // optional\n    invoicedName: user.name, // optional\n    invoicedDetail: \"Paid Access\", // optional\n  });\n\n  // Save and associate invoice to user\n  await user.update({ invoiceId: invoice[\"id\"]} );\n\n  // Use this object in the frontend to start the transaction.\n  res.json({ invoice });\n});\n```\n\nThe `invoice` object looks like this using TypeScript notation:\n\n```ts\ninterface PaymentInvoice {\n  id: string;\n  identifier: string;\n  state: PaymentInvoiceState;\n  amountPaid: string | BigNumber;\n  paidAt?: string;\n  address: string;\n  tokenAddress: string;\n  walletAddress: string;\n  invoicedPrice: string;\n  invoicedEmail?: string;\n  invoicedName?: string;\n  invoicedDetail?: string;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n\nexport enum PaymentInvoiceState {\n  Pending = \"PENDING\",\n  UnderPaid = \"UNDER_PAID\",\n  Paid = \"PAID\",\n  OverPaid = \"OVER_PAID\",\n}\n```\n\nSince any transaction sending money to the invoice address can fulfill the requested amount, one way to know the state of the payment is to ask Daisy via polling.\n\n```js\napp.get(\"/api/checkout/state/\", h(async (req, res) => {\n  const user = req.session;\n\n  try {\n    const invoice = await payments.getInvoice({\n      identifier: user.invoiceId,\n    });\n    const success = [\"PAID\", \"OVER_PAID\"].includes(invoice[\"state\"]);\n\n    res.json({ invoice });\n  } catch (error) {\n    //\n  }\n});\n```\n\nTo get the receipts from any Invoice:\n\n```js\nconst receipts = await payments.getReceipts({\n  identifier: user.invoiceId,\n});\n```\n\nReceipt object shape:\n\n```ts\ninterface PaymentReceipt {\n  id: string;\n  txHash: string;\n  account: string;\n  amount: string | BigNumber;\n  onChainCreatedAt: string | Date;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n```\n","readmeFilename":"README.md","gitHead":"43d96a987941ca22c38d2de53b52c86c4bd50d0e","description":"## Install","_id":"@daisypayments/daisy-sdk@0.8.0-beta.2","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-NkrwIw78UVmPnlzVaRz71vYmCswNUrUjbpVna9dSCXAKrkcVJd19J0WjNpkHALdMh7KXjg36By+ydcaNbDHX/w==","shasum":"f9669a03601d4d4a2b67a543b67f2b85259f6a54","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.8.0-beta.2.tgz","fileCount":18,"unpackedSize":293500,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd3t7yCRA9TVsSAnZWagAAmaIP+wZdA+rmRtebxSfOFBXE\nKNeEGOXOXO39tefa9E+hVxRklR/ZSyX1CkW/TcEoYh8AF05uJ0oMHYzogIqY\nq333O6ltDJ6S3V8VT91OzKql914LdYKK5cVtq4J7LxMGz4mlpFXOisMPSkeq\n2mVwaRj5z65jKcndjxUz+zB3neq7GowaGkAzdYcZXMtBwFwFj/X8FJRv9ohg\nds6+17pbE0mA9lPseCsCU+VdzJdoUxUlyiEwHFVm6JIgvM6HqbR87tT0ROXP\nAat8K4Nl6lbkj0VNa3b2JQeoi4MlfkKGO6fvqi2dlj2dE/jwoEjRZVdpr85D\n6MZ23XjARGaqygAM/k/2+9OryXVY5MyIpS3qjX3/yjUcKH0lPFpjf7HZgxp9\nhkbX4WHCzCQIEakEgqyyzW7NT6YxDdtnGxkclHKsa6x+6CaHFch8XSStbmpy\nTnXtDY7VGB+sMTE/T2IzUmuHz5RZkVAaBGfAM4dMevzvL/jDGAF8WuTEr+pz\nFmxfqBKXFefxZqx4kY3YevaKx5LDngLA2UO4TRfKyUW7sFwzfI+l/O9Pavij\n8XYIkoReTsY332Ijmg/ulvHYehu4MVmVJGgjLUOCm6RtWRGEteQKsrUii2GW\nYXNhuuOGUGlIgrXFUutDorTx5gjlqBA5M8IwIQoQROE0sfuyyvC3jaH5VOUw\niqeN\r\n=X2tl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDF9RGd+KBhHwVpYlMCAJt8iEzCtWcwtCx0l0XRIsovhwIgdTlhjX6D2u67GkqaR4H1o1MqELuwprQNASTstX0IWkc="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.8.0-beta.2_1574887154289_0.6309932079989415"},"_hasShrinkwrap":false},"0.8.0-beta.3":{"name":"@daisypayments/daisy-sdk","version":"0.8.0-beta.3","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.0","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.6.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.6.2","@babel/preset-env":"^7.6.3","@daisypayments/eslint-config":"^1.7.0","eslint":"^6.6.0","husky":"^3.0.9","jest":"^24.9.0","rollup":"^1.26.2","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `web3`, and `eventemitter3`\n\n```nocode\nyarn add @daisypayments/daisy-sdk eventemitter3 web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/Consensys/react-metamask).\n\n## Usage: Subscriptions\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServerSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServerSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nServerSubscriptions.fetch = fetch;\nconst subscriptions = new ServerSubscriptions({\n  manager: {\n    identifier: process.env.DAISY_ID,\n    secretKey: process.env.DAISY_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptions.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptions.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw new Error(\"Plan not found\");\n  }\n\n  const { data: subscription } = await subscriptions.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .prepareToken(token)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst { signature, agreement } = await daisy\n  .prepareToken(token)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst sub = await subscriptions.getSubscription({\n  id: daisyID,\n});\nconsole.log(sub[\"state\"]);\n\nconst subs = await subscriptions.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\nDaisy Invitation allows client to externalize the flow to Daisy's domain.\n\n#### 2.1 Recommended usage: WebHooks\n\nLet's say you created a Daisy Invitation with the following:\n\n```txt\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: {}\n\n```\n\nThis route (`callbackURL`) must handle a HTTP POST request and return a `2XX` status code.\n\n```ts\n// TypeScript typing\n\ntype ID = string;\n\n/**\n * JSON Payload attached to the POST request to `callbackURL`\n */\ninterface WebhookFromInvitation {\n  /**\n   * Semver string\n   * Current version: 1.0.0\n   */\n  version: string;\n  subscription: {\n    /**\n     * DaisyID\n     */\n    daisyId: ID;\n  };\n  plan: {\n    id: ID;\n    private: boolean;\n  };\n  invitation: {\n    id: ID;\n    automatic: boolean;\n  };\n  agreement: CreateSubscriptionAgreement;\n  /**\n   * When pre-signed (maybe because automatic was set to `true`) this field contains the authorizer signature.\n   * To void a pre-signed subscription, return `{ authSignature: null }` from the webhook.\n   */\n  authSignature: string | null;\n  extra: any;\n  /**\n   * Use SDK to verify this signature.\n   */\n  digest: string;\n}\n\ninterface CreateSubscriptionAgreement {\n  subscription: SubscriptionAgreement;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  previousSubscriptionId: string;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  credits: string;\n  nonce: string;\n  signatureExpiresAt: string;\n};\n\ninterface SubscriptionAgreement {\n  /**\n   * Ethereum address (subscriber)\n   */\n  subscriber: string;\n  /**\n   * Ethereum address (ERC20 Token)\n   */\n  token: string;\n  price: string;\n  /**\n   * DAY | MONTH | YEAR\n   */\n  periodUnit: string;\n  /**\n   * Number as string (blockchain stuff)\n   */\n  periods: string;\n  maxExecutions: string; // 0 = infinite\n  /**\n   * Plan's onChainId\n   */\n  plan: string;\n}\n```\n\nSo a normal server should handle this POST request like:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  // TODO: Identify the user\n  await user.patch({ daisyID: subscription[\"daisyId\"] });\n\n  // Optional redirect URL, may have custom tokens.\n  // Is not guaranteed the user is going to enter this URL.\n  const redirectURL = \"https://myapp.com/checkount/finish/\";\n\n  res.json({ authSignature, redirectURL })\n}));\n```\n\n#### 2.2 Voiding a subscription\n\nTo void a subscription and prevent the blockchain transaction set `authSignature` to `null`.\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  /* Void logic */\n\n  res.json({ authSignature: null });\n}));\n```\n\n> An alternative way of voiding is to return any response with a 400 or 500 HTTP status code.\n\n#### 2.3 Identifying the user\n\nOne way to identify an user after getting the callback is by knowing before-hand the user's Ethereum address.\nSo it can be queried from `req.body[\"agreement\"][\"subscriber\"]`\n\nA better way is setting the `callbackExtra` payload to something we can recognize in the backend.\nExample:\n\n```language\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: { \"email\": \"user@daisypayments.com\" }\n```\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, extra } = req.body\n\n  // TODO: Identify the user\n  await user.findById({ email: extra[\"email\"] }).patch({ daisyId: subscription[\"daisyId\"] });\n\n  // ...\n\n  const redirectURL = `https://myapp.com/checkount/finish/?user=${user.id}`;\n\n  res.json({ authSignature, redirectURL })\n}\n```\n\n#### 2.4 Verify authenticity\n\nTo tell if the webhook POST actually came from Daisy servers you can verify its signature:\n\n```js\nconst { verify } = require(\"@daisypayments/daisy-sdk/private/webhooks\");\nconst dedent = require(\"dedent\");\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { digest, ...payload } = req.body\n\n  const isAuthentic = verify({\n    message: payload,\n    digest: digest,\n    publicKey: dedent`\n      -----BEGIN PUBLIC KEY-----\n      MYIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyUaW5FK4ogS2/j7e7h65\n      u73/1QrdfocqHB14123kMQO6Z2CR1+dqa9afty3DQ+mLJ7gupOjvYFYrsiIQoMVc\n      J3zsmlYNjAnoHe8Kn2nU+Gjq+mJ6mscRIC6uMIMm/LslsiMugeL1YlpYXZ0uwbnY\n      TDKiC+g08iGc3tNiaFVCrzNcTH3221vasd321vh21UkWPcAJFDSR+YTtrXjpLMAB\n      jm3Vij8IarAmoCmTMIlUPbCb3j6NMjP4r0hulFUx6/u0DFvQPfKwzKnOph0CoX8u\n      kde74DGOsKxinYycP20w73aypC9eLY7M3PKtJCft3EypTEvgZRHG5Wd2BaTOvzF4\n      tQIDAGAB\n      -----END PUBLIC KEY-----\n    `,\n  });\n\n  if (!isAuthentic) {\n    // ...\n    res.json({ authSignature: null });\n  }\n\n  // ...\n});\n```\n\n## Usage: Payments invoices\n\n### 1. Creating invoices with Daisy SDK\n\n#### 1.1 Create an Invitation\n\nThe first step is going to the Daisy Dashboard and setup an Invitation product. After setting this go to the API Integration and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_OTP_ID=plantae\nDAISY_OTP_SECRET_KEY=key\n```\n\n#### 1.2 Server integration\n\nCreate an instance of `ServerPayments` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_OTP_SECRET_KEY` **private**.\n\n```js\nconst DaisySDK = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nconst payments = new DaisySDK.ServerPayments({\n  manager: {\n    identifier: process.env.DAISY_OTP_ID,\n    secretKey: process.env.DAISY_OTP_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nLet's say we want to sell an access pass for 20 USD or equivalent in DAI.\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\napp.get(\"/api/checkout/invoice/\", h(async (req, res) => {\n  const user = req.session;\n\n  // Create an invoice using Daisy SDK\n  const invoice = await payments.createInvoice({\n    invoicedPrice: 20, // required\n    invoicedEmail: user.email, // optional\n    invoicedName: user.name, // optional\n    invoicedDetail: \"Paid Access\", // optional\n  });\n\n  // Save and associate invoice to user\n  await user.update({ invoiceId: invoice[\"id\"]} );\n\n  // Use this object in the frontend to start the transaction.\n  res.json({ invoice });\n});\n```\n\nThe `invoice` object looks like this using TypeScript notation:\n\n```ts\ninterface PaymentInvoice {\n  id: string;\n  identifier: string;\n  state: PaymentInvoiceState;\n  amountPaid: string | BigNumber;\n  paidAt?: string;\n  address: string;\n  tokenAddress: string;\n  walletAddress: string;\n  invoicedPrice: string;\n  invoicedEmail?: string;\n  invoicedName?: string;\n  invoicedDetail?: string;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n\nexport enum PaymentInvoiceState {\n  Pending = \"PENDING\",\n  UnderPaid = \"UNDER_PAID\",\n  Paid = \"PAID\",\n  OverPaid = \"OVER_PAID\",\n}\n```\n\nSince any transaction sending money to the invoice address can fulfill the requested amount, one way to know the state of the payment is to ask Daisy via polling.\n\n```js\napp.get(\"/api/checkout/state/\", h(async (req, res) => {\n  const user = req.session;\n\n  try {\n    const invoice = await payments.getInvoice({\n      identifier: user.invoiceId,\n    });\n    const success = [\"PAID\", \"OVER_PAID\"].includes(invoice[\"state\"]);\n\n    res.json({ invoice });\n  } catch (error) {\n    //\n  }\n});\n```\n\nTo get the receipts from any Invoice:\n\n```js\nconst receipts = await payments.getReceipts({\n  identifier: user.invoiceId,\n});\n```\n\nReceipt object shape:\n\n```ts\ninterface PaymentReceipt {\n  id: string;\n  txHash: string;\n  account: string;\n  amount: string | BigNumber;\n  onChainCreatedAt: string | Date;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n```\n","readmeFilename":"README.md","gitHead":"42f5b03775dd0dab213d03dcffc7374f03f05f58","description":"## Install","_id":"@daisypayments/daisy-sdk@0.8.0-beta.3","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-xQalpyeyR78LyteDQBVYQ0r/YwXmB9LZZd74u83vH5MwtYRWq1s3sJ/U6yYXpd9LPy8SeOaEqY28Ivz2wARriA==","shasum":"a11c63172cb5e8e05d6619d6b6ce45f930de1b6b","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.8.0-beta.3.tgz","fileCount":18,"unpackedSize":293795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd4RaMCRA9TVsSAnZWagAAw30P/0m7rgC4ZWRbKRujuKcl\n1bppTn/MYrDXOGHsBDQ/QneUFLqzkVB4ZEUGboPo6sPQZKgpzdBZfxPyxpcf\nDCsgw1IiBJDvFmX0/ny6pvk0ekXeOntOXi1+xW84RnW7DlszsGvD24WmF2kA\npun2+0u2Lw/Oe7m7f1L7NewN4UzEf34jK9/PrNISEo7ecuL6SXw3hQP8SpYI\ndfQoakgzFqp7PXlI7ZjY9ghoiy0cQZkMEmJXI4gnStmSoNPtEGF+5rHKcq1t\nsLYgjksHA0P1xXhgvuRRRFyLdvdlpa/YPtcHnJ0UTqhSEZm7BJn2mpApzsMo\nl2DkW+USknyjkv7RhWIfKbQPVhDPzLoKElopJKkIlqFMOu0BayZ7nbWmzjGl\nEZobq32x55i3T1nIfEYS2nULUGiIxdrxCPhrheGbSburs5M51mej1hIvfhsi\nawN23/QjBQAht+zIs7ReNX3W4/qQWL7VrKUz87z+RUfXCS0fDJOw9GnxIll+\n2ZCozMMCgpGhq+vruD0mMcxx6wCYIjT67Kiog+2AO6/08TRvFid0TKMScZS9\ngq3Gx2iRzNQaLVb/xm43cvKdbTx/cE1OkpgXhyr6a3oFBE1sTHxxF8OKvERm\nrqjfqe2TPhFr+EMkYn6v9ElP2ks7r9NK85OakKO+T8iBjZDXe5KWa8AFVJ/1\nYFbs\r\n=yTbq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICvEkkxbkE5Hco4CiIZPOHfljJaSuC5KEm8aHbWm+UW+AiEA1y8gwu52STE51E/GDY08R5Fe5BlFJY3fDsB2crynCjs="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.8.0-beta.3_1575032459251_0.5661115074854077"},"_hasShrinkwrap":false},"0.8.0-beta.4":{"name":"@daisypayments/daisy-sdk","version":"0.8.0-beta.4","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.0","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.6.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.6.2","@babel/preset-env":"^7.6.3","@daisypayments/eslint-config":"^1.7.0","eslint":"^6.6.0","husky":"^3.0.9","jest":"^24.9.0","rollup":"^1.26.2","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `web3`, and `eventemitter3`\n\n```nocode\nyarn add @daisypayments/daisy-sdk eventemitter3 web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/Consensys/react-metamask).\n\n## Usage: Subscriptions\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServerSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServerSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nServerSubscriptions.fetch = fetch;\nconst subscriptions = new ServerSubscriptions({\n  manager: {\n    identifier: process.env.DAISY_ID,\n    secretKey: process.env.DAISY_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptions.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptions.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw new Error(\"Plan not found\");\n  }\n\n  const { data: subscription } = await subscriptions.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .prepareToken(token)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst token = daisy.loadToken(plan); // web3.js contract instance\n\nconst { signature, agreement } = await daisy\n  .prepareToken(token)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst sub = await subscriptions.getSubscription({\n  id: daisyID,\n});\nconsole.log(sub[\"state\"]);\n\nconst subs = await subscriptions.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\nDaisy Invitation allows client to externalize the flow to Daisy's domain.\n\n#### 2.1 Recommended usage: WebHooks\n\nLet's say you created a Daisy Invitation with the following:\n\n```txt\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: {}\n\n```\n\nThis route (`callbackURL`) must handle a HTTP POST request and return a `2XX` status code.\n\n```ts\n// TypeScript typing\n\ntype ID = string;\n\n/**\n * JSON Payload attached to the POST request to `callbackURL`\n */\ninterface WebhookFromInvitation {\n  /**\n   * Semver string\n   * Current version: 1.0.0\n   */\n  version: string;\n  subscription: {\n    /**\n     * DaisyID\n     */\n    daisyId: ID;\n  };\n  plan: {\n    id: ID;\n    private: boolean;\n  };\n  invitation: {\n    id: ID;\n    automatic: boolean;\n  };\n  agreement: CreateSubscriptionAgreement;\n  /**\n   * When pre-signed (maybe because automatic was set to `true`) this field contains the authorizer signature.\n   * To void a pre-signed subscription, return `{ authSignature: null }` from the webhook.\n   */\n  authSignature: string | null;\n  extra: any;\n  /**\n   * Use SDK to verify this signature.\n   */\n  digest: string;\n}\n\ninterface CreateSubscriptionAgreement {\n  subscription: SubscriptionAgreement;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  previousSubscriptionId: string;\n  /**\n   * Ignore. this is for future compatibility\n   */\n  credits: string;\n  nonce: string;\n  signatureExpiresAt: string;\n};\n\ninterface SubscriptionAgreement {\n  /**\n   * Ethereum address (subscriber)\n   */\n  subscriber: string;\n  /**\n   * Ethereum address (ERC20 Token)\n   */\n  token: string;\n  price: string;\n  /**\n   * DAY | MONTH | YEAR\n   */\n  periodUnit: string;\n  /**\n   * Number as string (blockchain stuff)\n   */\n  periods: string;\n  maxExecutions: string; // 0 = infinite\n  /**\n   * Plan's onChainId\n   */\n  plan: string;\n}\n```\n\nSo a normal server should handle this POST request like:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  // TODO: Identify the user\n  await user.patch({ daisyID: subscription[\"daisyId\"] });\n\n  // Optional redirect URL, may have custom tokens.\n  // Is not guaranteed the user is going to enter this URL.\n  const redirectURL = \"https://myapp.com/checkount/finish/\";\n\n  res.json({ authSignature, redirectURL })\n}));\n```\n\n#### 2.2 Voiding a subscription\n\nTo void a subscription and prevent the blockchain transaction set `authSignature` to `null`.\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, authSignature } = req.body\n\n  /* Void logic */\n\n  res.json({ authSignature: null });\n}));\n```\n\n> An alternative way of voiding is to return any response with a 400 or 500 HTTP status code.\n\n#### 2.3 Identifying the user\n\nOne way to identify an user after getting the callback is by knowing before-hand the user's Ethereum address.\nSo it can be queried from `req.body[\"agreement\"][\"subscriber\"]`\n\nA better way is setting the `callbackExtra` payload to something we can recognize in the backend.\nExample:\n\n```language\nidentifier: \"/i/af4cff8c\"\ncallbackURL: https://myapp.com/api/callback/daisy-invitation/\ncallbackExtra: { \"email\": \"user@daisypayments.com\" }\n```\n\n```js\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { subscription, plan, extra } = req.body\n\n  // TODO: Identify the user\n  await user.findById({ email: extra[\"email\"] }).patch({ daisyId: subscription[\"daisyId\"] });\n\n  // ...\n\n  const redirectURL = `https://myapp.com/checkount/finish/?user=${user.id}`;\n\n  res.json({ authSignature, redirectURL })\n}\n```\n\n#### 2.4 Verify authenticity\n\nTo tell if the webhook POST actually came from Daisy servers you can verify its signature:\n\n```js\nconst { verify } = require(\"@daisypayments/daisy-sdk/private/webhooks\");\nconst dedent = require(\"dedent\");\n\n// POST /api/callback/daisy-invitation/ -> Daisy callback handler\napp.post(\"/api/callback/daisy-invitation/\", h(async (req, res) => {\n  const { digest, ...payload } = req.body\n\n  const isAuthentic = verify({\n    message: payload,\n    digest: digest,\n    publicKey: dedent`\n      -----BEGIN PUBLIC KEY-----\n      MYIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyUaW5FK4ogS2/j7e7h65\n      u73/1QrdfocqHB14123kMQO6Z2CR1+dqa9afty3DQ+mLJ7gupOjvYFYrsiIQoMVc\n      J3zsmlYNjAnoHe8Kn2nU+Gjq+mJ6mscRIC6uMIMm/LslsiMugeL1YlpYXZ0uwbnY\n      TDKiC+g08iGc3tNiaFVCrzNcTH3221vasd321vh21UkWPcAJFDSR+YTtrXjpLMAB\n      jm3Vij8IarAmoCmTMIlUPbCb3j6NMjP4r0hulFUx6/u0DFvQPfKwzKnOph0CoX8u\n      kde74DGOsKxinYycP20w73aypC9eLY7M3PKtJCft3EypTEvgZRHG5Wd2BaTOvzF4\n      tQIDAGAB\n      -----END PUBLIC KEY-----\n    `,\n  });\n\n  if (!isAuthentic) {\n    // ...\n    res.json({ authSignature: null });\n  }\n\n  // ...\n});\n```\n\n## Usage: Payments invoices\n\n### 1. Creating invoices with Daisy SDK\n\n#### 1.1 Create an Invitation\n\nThe first step is going to the Daisy Dashboard and setup an Invitation product. After setting this go to the API Integration and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_OTP_ID=plantae\nDAISY_OTP_SECRET_KEY=key\n```\n\n#### 1.2 Server integration\n\nCreate an instance of `ServerPayments` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_OTP_SECRET_KEY` **private**.\n\n```js\nconst DaisySDK = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nconst payments = new DaisySDK.ServerPayments({\n  manager: {\n    identifier: process.env.DAISY_OTP_ID,\n    secretKey: process.env.DAISY_OTP_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nLet's say we want to sell an access pass for 20 USD or equivalent in DAI.\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\napp.get(\"/api/checkout/invoice/\", h(async (req, res) => {\n  const user = req.session;\n\n  // Create an invoice using Daisy SDK\n  const invoice = await payments.createInvoice({\n    invoicedPrice: 20, // required\n    invoicedEmail: user.email, // optional\n    invoicedName: user.name, // optional\n    invoicedDetail: \"Paid Access\", // optional\n  });\n\n  // Save and associate invoice to user\n  await user.update({ invoiceId: invoice[\"id\"]} );\n\n  // Use this object in the frontend to start the transaction.\n  res.json({ invoice });\n});\n```\n\nThe `invoice` object looks like this using TypeScript notation:\n\n```ts\ninterface PaymentInvoice {\n  id: string;\n  identifier: string;\n  state: PaymentInvoiceState;\n  amountPaid: string | BigNumber;\n  paidAt?: string;\n  address: string;\n  tokenAddress: string;\n  walletAddress: string;\n  invoicedPrice: string;\n  invoicedEmail?: string;\n  invoicedName?: string;\n  invoicedDetail?: string;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n\nexport enum PaymentInvoiceState {\n  Pending = \"PENDING\",\n  UnderPaid = \"UNDER_PAID\",\n  Paid = \"PAID\",\n  OverPaid = \"OVER_PAID\",\n}\n```\n\nSince any transaction sending money to the invoice address can fulfill the requested amount, one way to know the state of the payment is to ask Daisy via polling.\n\n```js\napp.get(\"/api/checkout/state/\", h(async (req, res) => {\n  const user = req.session;\n\n  try {\n    const invoice = await payments.getInvoice({\n      identifier: user.invoiceId,\n    });\n    const success = [\"PAID\", \"OVER_PAID\"].includes(invoice[\"state\"]);\n\n    res.json({ invoice });\n  } catch (error) {\n    //\n  }\n});\n```\n\nTo get the receipts from any Invoice:\n\n```js\nconst receipts = await payments.getReceipts({\n  identifier: user.invoiceId,\n});\n```\n\nReceipt object shape:\n\n```ts\ninterface PaymentReceipt {\n  id: string;\n  txHash: string;\n  account: string;\n  amount: string | BigNumber;\n  onChainCreatedAt: string | Date;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n```\n","readmeFilename":"README.md","gitHead":"de7369b2a6bd38b25fc8882a6a3d620b77b7c94d","description":"## Install","_id":"@daisypayments/daisy-sdk@0.8.0-beta.4","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-fohQazk+3VtR2ui0h5ytpD5qUtAKZkvqtW66JAZYzvhbuJ2aqqvKQw3EMMaMJvs6hoh8e5ScU/qVzbynA8amXQ==","shasum":"2d23a3d1ccd2058fc0179f597799c35390b59c7a","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.8.0-beta.4.tgz","fileCount":18,"unpackedSize":295101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd4THACRA9TVsSAnZWagAAN2IP/3b6lHVeNjk/DBiBJZZ8\nlE14bAMCt34Ls4eS3lAWKdWJI4SR440Ff2shKzyYUHEVUT346x0SIaKK4QBd\ngil622r0LpD804X/U4MfWu4esMMMTtF6hQo0PhOVzO1YG4h28oSUi2hMvA70\nlNjHw6VwfGodGhzz/PopplfDRihMcdUhx9Ul9iJiUBgBPlh5eGByL1RKoEK8\nmaMypf5NbefOxRMHlR9bIyIAe16iW8BIeuACzs+QS30xCj7Svhzyd8ROj3X4\nn41XBPukIqLQyp6nRweJQ4YGJlk9b/8BKBNZ8RTYm2va9VPkiQQ9K56miYjr\nWlmmnY/lN9nHtWhh7/MCIJyw5F2NUC9S051a2DyJCbIjLyeacmKGWe/ucZj4\nocZ8/IW34G0CtGoIKOdU2n8XwbMS+iEQ1W9GcTQ11AgyloqPTS8XszlejYsL\n1wFi1R9m1J91CsacISph0EFC49vVzwW5bPIKj/oh2oan3y4jQr+a5MVLzS3F\nV21dM3pmnRQwsqt5b1LQ1yR/p2bqOeWECJmHpmYaHBjoSfHb6gjiF9iP61g3\nK4xmqWAJz2i2Ej1yc2djpbS6Y7mTFRcrSaj8TqVeD6R6AWHnu2IXDouxP2jo\nLfMj64pyzL41Yy6kr7VmQPeXtv8yGHCc3LgRzsINoNs6l0Hppm+dogMCzm0k\nSutg\r\n=q3Um\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGBrjutk4ZkGlE1Pd8/pnFG29KilJHLr3ncyAG62rqaDAiA29gzg44pTRAsmxLlCa96TepZ6oXbUw4M6VpbrrkVziA=="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.8.0-beta.4_1575039424044_0.8190575279001857"},"_hasShrinkwrap":false},"0.8.0":{"name":"@daisypayments/daisy-sdk","version":"0.8.0","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.0","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.6.4","@babel/plugin-external-helpers":"^7.2.0","@babel/plugin-proposal-class-properties":"^7.5.5","@babel/plugin-proposal-object-rest-spread":"^7.6.2","@babel/preset-env":"^7.6.3","@daisypayments/eslint-config":"^1.7.0","eslint":"^6.6.0","husky":"^3.0.9","jest":"^24.9.0","rollup":"^1.26.2","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"gitHead":"38af1663f00d1089c7b269e1c462c06073678d76","description":"## Install","_id":"@daisypayments/daisy-sdk@0.8.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-U33O00HEiHkWKPwtHPH34wqcTmL8JbdHgYi3tsbdtJ7fOS2qoD8RX1JTPYoBAz2jlV3XkkfT0ZQRKtXh/Ppy3g==","shasum":"25c41ce373443efe99b728d98a48a78fd01870cb","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.8.0.tgz","fileCount":18,"unpackedSize":349633,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd5qv3CRA9TVsSAnZWagAAXTUQAJc9sf+XSE8ekzy3ecol\ne7Rlq6TNRO6tutSZ/QHQD/eX9m7HE56p/aqiztvovc78RGJMUet0ZpWMyBgD\nEkzVoGdB8ePCVMb9BhStkj/i0UK51Woth15SmOTXmDt9PxGGylXKz1myFDXr\nsg+PWis8XYqj+Xi9g8Th9BbHiteOWCSnXSi83GPgK/gtMfcWn6S0xdoo7bde\nHvbHlsg2cG7zw83hQed9Nv5wTTWorQ6xmPIGAwn9U6czKQA/Zq36A4XJaLOB\ngMS8hxWU0vDB9f3Ei535CRQdbD120sXctqY0dYSYglslLRQ3/1AwjJDjLjPH\nlFCRsPfVufK7vBtkmevRMoEI23DQAVMwK6+spIDOqhcxjhgtYGjGy38QaUri\nf6fVXjft9BGVzcjmN0jQcvomv2DP1iYF+Jcuww71L4MAjOq8Udf8CL9K6i+P\nUEXs/CysC4MuXCH1gWsN3/QPPEIC3oymfNH22V0/y3Zw0nq3c+QD9nEx3PN+\nLFFFET7nyksWw86DQVhaJaQksVXhj4Jsaw8jCawUdEqitsHaMsRMx0bunEqy\n+TMvpYes+ZHP5BlFHR1vXlKqPJuxJjCJRvw8dVDWiVy2dleSY8yLVujoZ1dv\nMfrsESGtoQe7THomSUD8i/sP2OEmdYSrbpG8I09OiFk36nytjInyCfD3mq13\naUkP\r\n=/JR0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB497bJcEq5VhQQMSjVcyPrsgfKoRwhnZfesd19cqps+AiAS/uEetwOxmtMEexR5/fHeZEDyIvZjCS8OsA1pMA+Dvg=="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.8.0_1575398391000_0.8641204894872423"},"_hasShrinkwrap":false},"0.9.0":{"name":"@daisypayments/daisy-sdk","version":"0.9.0","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.2","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.7.5","@babel/plugin-external-helpers":"^7.7.4","@babel/plugin-proposal-class-properties":"^7.7.4","@babel/plugin-proposal-object-rest-spread":"^7.7.4","@babel/preset-env":"^7.7.6","@daisypayments/eslint-config":"^1.7.0","bignumber.js":"^9.0.0","dotenv":"^8.2.0","eslint":"^6.7.2","husky":"^3.1.0","jest":"^24.9.0","rollup":"^1.27.9","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"gitHead":"2f7624e9aa3f8aa09ea1a86ec77a7306d2539e3c","description":"## Install","_id":"@daisypayments/daisy-sdk@0.9.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-soySuyE1PBbhMQlH/GfOYS750o+fy3LaGyGAgV4CmTDURzEa8G7ApQLsisUUnuWzCzEyZjRqTAUV6WOZdvIcYA==","shasum":"f1a2a40e0f2743d148817b9511a231ffbf06602c","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.9.0.tgz","fileCount":18,"unpackedSize":391459,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeAMj+CRA9TVsSAnZWagAAcRcQAKToH6hfKBJ+D4OKlsI2\nFXNFNhu5fTuRSwyo26WsZkuJbi+vAss2NmZhYAAR8bqYnfNG0OXsR5nvhePn\nLSg2PjM2rEihFfq3UXl8V0OY9X2IJyNw7IIRGq2Jqio7rizmbmh7Ky++g1ea\nquFpWHUO3MZxialWzuVqidgy+1ytoAWQVJ81tnEjkD9sxPBvzqoZjIS5EThI\nVxowN1eBXBIRKGN9bR6GIsbWLAHuFDcaZqnJ0Abx4mFcaO1xj7Sk0EKa4Dmf\ntClxgfpK+td59dbsJS18cuBxptaWpHWkkRjX1PVmYYtnAmGgnCcHDZSPnpld\nh6GsDs21L70UhSgpwthf+AMVt7yp9IDnmO7I7EWt/iUwo/VJJ9EkDkh/6ybq\nEu6oNgWyp8QnONJYcIodwgaK6l7Jv8+YJekn9dEycwhGdtwEwssiBqmDchOA\nJE2rnOsWpz8j6HqOmemyWJQ43MacXXoN7++7iD7pZ4joB/b/KaVCrcws8yxb\nubktJiEbNtErmwFYWkQzhfbQ3rH2qFmFIYjOD/qnGUoGRJ+/WYn/98AxNU2H\nxaJvdMsbTZN1AlApCxUE/Z+CL+8RinmFhGHe1cf96slLDcpZ0dkl96mq5F7p\nHCRoYcFXeSwovuXbUFmH6uPU4OytudG1SxC/g91sgFIW5To4Vr23KozeU6ur\nP1ka\r\n=DQLL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCOKDC1GgqD70nOIdfRjVTESoH/B5IODrT6V8AbQgXBcAIhAMx4D0l9+Tc3XMTKrYE4AWDgNPTO+1ZixC2KnQEM+p7X"}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.9.0_1577109757944_0.4476944088872621"},"_hasShrinkwrap":false},"0.10.0":{"name":"@daisypayments/daisy-sdk","version":"0.10.0","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.2","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.7.5","@babel/plugin-external-helpers":"^7.7.4","@babel/plugin-proposal-class-properties":"^7.7.4","@babel/plugin-proposal-object-rest-spread":"^7.7.4","@babel/preset-env":"^7.7.6","@daisypayments/eslint-config":"^1.7.0","bignumber.js":"^9.0.0","dotenv":"^8.2.0","eslint":"^6.7.2","husky":"^3.1.0","jest":"^24.9.0","rollup":"^1.27.9","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"gitHead":"e371d51240c351cee69dab1a3a5d0d0f97581900","description":"## Install","_id":"@daisypayments/daisy-sdk@0.10.0","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-pTLp5IvNkznkEzYwIMvLoio6hSeA3MFWgKoqTYAMW15g1pLGBjzvyVLbDUIces0gCvRxkXBqDUbc+Ui58j49lQ==","shasum":"d6b4d7227a2af3ba4c0a8b3eaba974ff6d678eb6","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.10.0.tgz","fileCount":18,"unpackedSize":400325,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVrBpCRA9TVsSAnZWagAAcLEP/itVUWERSqwdUlmavKxJ\nWYxNwb87y92xbTMxpzzUNmESchW4rYYM5NFmA38rVXrrv6/LqwnBvBn9FVLX\n4zpG5E8p/9kbpJIb8jPfQht+luWL1Qa1JLCoFAzvFxiKGjMprV8cIimxLjOk\nLqJ9WQ+zlZD2qc/CeKS86CJVZrJkmMwJIKtvwlzG2PX5z4pjfUE0e0ZxgCV5\nYFueelASo49GmYvmPz75dpkAe+VRAOXpIlqEvJp4W1/g/4gfTG5Pc7Mo7x3H\niDhu19BWYxgETWdtieLnPY3e4OtGxBUPlGJu8wwM4Ahx0yJGtBd8uUJBd8XU\nb7H+YqkGoMoy5Jn9HXWNxIQLWnrjBrIcCFjU+E5WVRNNbyXNHdI+RQMg3Awi\nRGcmGLCX9OcgP4mmFmpJ7uLsk/lneoAQKm9NuErgsYT4eZjN5zDKSa7SX+Jl\nDSqaYC4JMLVPErL/WlHfPGzk+hkxZJr1Ud3nGD2V1NqPkJNSEUgmU4a13an7\npP79u9GOLGK+8evA3beno6DQlO0TIKIy95eWrDsHKXKm7q49jTMk0u298Yjn\n613nQXM7g5AZFGr91+2xXvn/NfLrf2XxDEfzul3jup+CH/p5rKoNboFKiGXM\n/2YAr54oC9U68cX7vK0NwWfwCQMjJ+/kII0n0opzW4Uk2yswzdspeqPo/jm3\nMHL6\r\n=MdSR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHpu68sNa6f10u1LblOGMdLmRWSo2R+ArfJBObNpY0QKAiAXX2UhdobUk6SYarHGpfLIizWzVQx0LaJJ7O9b1SIGjQ=="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.10.0_1582739561208_0.9253340276454538"},"_hasShrinkwrap":false},"0.11.0":{"name":"@daisypayments/daisy-sdk","version":"0.11.0","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.2","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.7.5","@babel/plugin-external-helpers":"^7.7.4","@babel/plugin-proposal-class-properties":"^7.7.4","@babel/plugin-proposal-object-rest-spread":"^7.7.4","@babel/preset-env":"^7.7.6","@daisypayments/eslint-config":"^1.7.0","bignumber.js":"^9.0.0","dotenv":"^8.2.0","eslint":"^6.7.2","husky":"^3.1.0","jest":"^24.9.0","rollup":"^1.27.9","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"gitHead":"7183ff171295cc8f8f6f286a15d890676f6ded08","description":"## Install","_id":"@daisypayments/daisy-sdk@0.11.0","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-CBjSHSHhF2GRsIPyMoX3MFY1hIDXiPg+x8bllM85CtwxDLqLtGKfHJxTvu7BLMmbSrY4AbM3qm/CtSSSqcGXoA==","shasum":"b1e60a6115ec430774399b8f488782bbd51b3811","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.11.0.tgz","fileCount":18,"unpackedSize":395617,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelMsLCRA9TVsSAnZWagAAM9EP/0ZRhJNK464JdPKDznad\njWu0Rtc7rYyKl15YOnkcyTq3vgkbim8/mtxc7LvnTHfTaHGE6CIbZ7ib2Jvs\niZyp4gySEkYSN/u3i8asd/ETxWt8ijIFwzJoWMt4v1L/JgdtQmPWMMBk4mtF\npZ5f2O6UFt5DpRNyRa08NTiGnl18HHVZvk+6mwWeFc1w9Ga7K3oXT8LSzBEI\notL09fPh5CIBnd1VEFCHEPBEBP+/ohTAk+Ruxspvx+hSd/6Z87B8x3ianPTc\nKqampriOf0WCjk3FsXPODefVrTxbUPORAkorLhX0lhaLCX6si8FbbFs1L0VO\nLmVhl67rOSEsNsLIYknLahwmvvkAGCJYBM7YnvLAMRg4laq5L+zzZNISryWz\n2sPEA9QaSKzxv68DDe3wZIUhhaKytPJNwA1vRYKD3zj4IeyEdD64pRny3ep+\n/f5Vp+jYUT2Vh37a4kIlj8c04k94R5SMOoSlspm7c6KKRIrGFf0V1d1U8qNg\nBNBb6yBrsDnSuLL1Ndu5DBYOc7q1BBniO3ZknMQ27yN4jqdLSpFCEhaFRh7+\np41Lb/Bt4gFrVks8/ji5WenrVnDfxstACJ7XCKMIA7GBmmLivTBRl5dmzzM5\nUgPLwk2HG/WG1eGpD72Kpue7h70uxsdj3AvYW//PQFxRNmG65IKPAj6/RoOt\nIW+G\r\n=Q9Sn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFaRioSbluQ+xfdxCsVKX2zgTJ1hF2b2axbjaHf7gqEWAiEAmBTcg/56a8mUxYxRG7ucJB+F2sGhq3act/EGN2LapfM="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.11.0_1586809611234_0.6409209447864752"},"_hasShrinkwrap":false},"0.11.1":{"name":"@daisypayments/daisy-sdk","version":"0.11.1","main":"dist/index.js","module":"dist/index.es.js","jsnext:main":"dist/index.es.js","private":false,"license":"MIT","scripts":{"build":"rollup -c","lint":"eslint --cache","test":"jest"},"husky":{"hooks":{"pre-commit":"yarn run lint ."}},"dependencies":{"@daisypayments/smart-contracts":"^0.2.2-beta","eth-sig-util":"^2.5.2","eventemitter3":"^4.0.0","node-fetch":"^2.6.0"},"peerDependencies":{},"devDependencies":{"@babel/core":"^7.7.5","@babel/plugin-external-helpers":"^7.7.4","@babel/plugin-proposal-class-properties":"^7.7.4","@babel/plugin-proposal-object-rest-spread":"^7.7.4","@babel/preset-env":"^7.7.6","@daisypayments/eslint-config":"^1.7.0","bignumber.js":"^9.0.0","dotenv":"^8.2.0","eslint":"^6.7.2","husky":"^3.1.0","jest":"^24.9.0","rollup":"^1.27.9","rollup-plugin-babel":"^4.3.3","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0"},"optionalDependencies":{"node-fetch":"^2.6.0"},"gitHead":"ab7fc2dbea0b6922f9b7142b1f7ba247fc0e0d5d","description":"## Install","_id":"@daisypayments/daisy-sdk@0.11.1","_nodeVersion":"10.18.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-TPya7IR5hCXY+aDVNpTrt8kh/S3bTlytnsiB1cGKCWWz8Py2FzXgC5Gya1MAnD9T1iBFIEUuwxv3ycUgVlp1HA==","shasum":"269cbc5fe2606e088db3e7e69090edbfcab0a5eb","tarball":"https://registry.npmjs.org/@daisypayments/daisy-sdk/-/daisy-sdk-0.11.1.tgz","fileCount":18,"unpackedSize":395739,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelNH5CRA9TVsSAnZWagAAr4QP/306DvdkmnwTT62F6oqA\nsE1aCEM4ndG/22fOksSZ/yD3yN0j2ZLNodnNU8OHx8uAjAcibT6SLUN04is+\n8h7Ryc4oj/3VZBtc25idi/v0sSP8scI995zjdmwrwgIBKTObP1CN5V3kUPPc\noBAUkM+DQ5OC/zXJhprt4n0NC5LX2b4IE1ILp7Zis+H6J+Z8hltSCxpLuOLi\n8mN57DYbgeoZ7Z2aNZLNNO7Tb2cBJcSKR4v4QPqgdMyQKxuhVlBRdcIaqYai\nxcxf8Ncs3lcg2BQeuYDDeRiNhxNVC9K41X8wrrYNdy5BorKUxMmM/fr28h6m\nTNt1MGvuO7zJSjJQDuTs2JxvgyXf7BZISS+kLDWMagb6sfYMTVSARpJdScXY\nFvgxo6/KiOB8MDLnsA0wFoYNM7uXiy5G35RQZS4lBLF3YtxwraTxx7YXgSX4\nZXx+1pxolJTmW023U9xW7323zea+IKltEqRM9g9k+21hvNo0BW46B3ha32gh\nPLAt5qC9I7o92dtWQExV3dIhDsTzBqlSQIjZrYAVHlnB7AwUBufsaPtCTE/+\ndS8LnfVO9ADBuqFo3SATxrnaAThr5JyeJLETHEr39vLHSc1vUUH5V7Cl0VSA\nm80VR3Ciz/p6SlHhW1kqmZ+MP/kkQPQfNtwxZk5VAoQ+fwMnwWwmZdUDHz1k\nne4A\r\n=LCP2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDS5xt4zi2BQASogYaO48xSvKbvZsoVb6+MXd/10gk1ygIgfk1730O9fPMsp5FolrG7kp9ANySj4DLRtlkZqh9o5EE="}]},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"_npmUser":{"name":"lopezjurip","email":"lopezjuripatricio@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/daisy-sdk_0.11.1_1586811384888_0.8756883409894094"},"_hasShrinkwrap":false}},"time":{"created":"2019-07-03T16:44:12.631Z","0.5.2":"2019-07-03T16:44:12.992Z","modified":"2022-04-05T02:36:43.578Z","0.6.0":"2019-07-18T14:53:11.410Z","0.6.1":"2019-07-25T15:01:06.067Z","0.7.0":"2019-08-22T15:30:24.205Z","0.7.0-beta.1":"2019-09-20T17:59:53.875Z","0.7.0-beta.2":"2019-11-07T21:36:37.421Z","0.8.0-beta.1":"2019-11-27T17:14:29.657Z","0.8.0-beta.2":"2019-11-27T20:39:14.436Z","0.8.0-beta.3":"2019-11-29T13:00:59.705Z","0.8.0-beta.4":"2019-11-29T14:57:04.174Z","0.8.0":"2019-12-03T18:39:51.155Z","0.9.0":"2019-12-23T14:02:38.041Z","0.10.0":"2020-02-26T17:52:41.330Z","0.11.0":"2020-04-13T20:26:51.472Z","0.11.1":"2020-04-13T20:56:25.042Z"},"maintainers":[{"email":"jmoreiras@gmail.com","name":"jmoreira"},{"email":"lopezjuripatricio@gmail.com","name":"lopezjurip"},{"email":"nate.chastain@consensys.net","name":"nchastain"},{"email":"lhloreti@gmail.com","name":"sloreti"},{"email":"vdrg@protonmail.ch","name":"vdrg"},{"email":"wachunei@gmail.com","name":"wachunei"}],"description":"## Install","license":"MIT","readme":"# Daisy SDK\n\n## Install\n\n> You may also require some extra dependencies like `web3`, and `eventemitter3`\n\n```nocode\nyarn add @daisypayments/daisy-sdk eventemitter3 web3@1.0.0-beta.37\n```\n\n## MetaMask helper\n\nTo help you handle web3 instances and the current account we recommended [daisypayments/react-metamask](https://github.com/Consensys/react-metamask).\n\n## Usage: Subscriptions\n\n### 1. Standard private and public plans with DaisySDK\n\nThis is the default flow with standardized plans. This requires the implementation of a front-end with integration of Daisy Widget or Daisy SDK (advanced).\n\n#### 1.1 Create a Subscription Product and Plans\n\nAfter deploying a Subscription Product to the blockchain go to the *API Integration* tab and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_ID=margarita\nDAISY_SECRET_KEY=key\nDAISY_CALLBACK_PUBLIC_KEY=key\n```\n\n#### 1.2 Integration in the server\n\nCreate an instance of `ServerSubscriptions` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_SECRET_KEY` **private**.\n\n```js\nconst { ServerSubscriptions } = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nServerSubscriptions.fetch = fetch;\nconst subscriptions = new ServerSubscriptions({\n  manager: {\n    identifier: process.env.DAISY_ID,\n    secretKey: process.env.DAISY_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nCreate and endpoint to retrieve information from your servers back to the frontend.\nHere is an example using Express.js:\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\n// GET /api/plans/ -> Fetch plans from the frontend\napp.get(\"/api/plans/\", h(async (req, res) => {\n  const { plans } = await subscriptions.getData();\n  res.json({ plans });\n}));\n\n// POST /api/plan/:pid/subscriptions/ -> Submit a subscription to Daisy\napp.post(\"/api/plan/:pid/subscriptions/\", h(async (req, res) => {\n  const user = req.session;\n  const { agreement, signature } = req.body;\n\n  const { plans } = await subscriptions.getData();\n  const plan = plans.find(p => p[\"id\"] === req.params[\"pid\"]);\n  if (!plan) {\n    throw new Error(\"Plan not found\");\n  }\n\n  const { data: subscription } = await subscriptions.submit({\n    agreement,\n    authSignature,\n    signature,\n  });\n\n  // Save and associate DaisyID from `subscription[\"daisyId\"]` to an user.\n  const daisyId = subscription[\"daisyId\"];\n  await user.patch({ daisyId });\n\n  res.send(\"ok\");\n}));\n```\n\n##### 1.2.1 Get plans from the frontend (not recommended)\n\nThis will only expose `private: false` plans.\n\n```js\nimport DaisySDK from \"@daisypayments/daisy-sdk\";\n\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst { plans } = await daisy.getData();\n```\n\n#### 1.3 Approving tokens\n\nIt is required to approve tokens before signing the subscription agreement.\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst approvalAmount = \"9000000000000000\";\nconst account = \"0x...\" // from MetaMask.\n\nconst eventemitter = daisy\n  .with(plan)\n  .approve(approvalAmount, { from: account });\n\nconst eventemitter\n  .on(\"transactionHash\", handleApprove_transactionHash)\n  .on(\"confirmation\", handleApprove_confirmation)\n  .on(\"receipt\", handleApprove_receipt)\n  .on(\"error\", handleApprove_error);\n\nfunction handleApprove_transactionHash(transactionHash) {\n  // ...\n};\nfunction handleApprove_confirmation(confirmationNumber, receipt) {\n  // ...\n};\nfunction handleApprove_receipt(receipt) {\n  // Here you can assume this task is complete.\n  // If you want to resume this transaction, save the `receipt` object.\n};\nfunction handleApprove_error(error) {\n  // ...\n};\n```\n\n#### 1.4 Signing subscription agreement\n\n```js\nconst daisy = await DaisySDK.initSubscriptions({\n  manager: { identifier: \"margarita\" },\n  withGlobals: { web3 },\n});\n\nconst { signature, agreement } = await daisy\n  .with(plan)\n  .sign({ account, plan });\n\n// Send `signature` and `agreement` back to the server\n// TODO: replace `:pid` with Plan ID.\nconst response = await fetch(\"/api/plan/:pid/subscriptions/\", {\n  method: \"post\",\n  credentials: \"same-origin\",\n  body: JSON.stringify({ signature, agreement }),\n});\n\nconst data = await response.json();\n```\n\n##### 1.4.1 Submit subscription from the frontend (only for public plans) (not recommended)\n\n```js\nconst { data: subscription } = await daisy.submit({\n  agreement,\n  signature,\n});\n```\n\n#### 1.5 Verify Daisy subscription state\n\nVerify subscription state with:\n\n```js\nconst sub = await subscriptions.getSubscription({\n  id: daisyID,\n});\nconsole.log(sub[\"state\"]);\n\nconst subs = await subscriptions.getSubscriptions({\n  account: \"0x...\",\n});\n```\n\n### 2. Invitations\n\n> This feature has been reworked and the documentation still in progress.\n\n## Usage: Payments invoices\n\n### 1. Creating invoices with Daisy SDK\n\n#### 1.1 Create an Invitation\n\nThe first step is going to the Daisy Dashboard and setup an Invitation product. After setting this go to the API Integration and grab the `DAISY_ID` and `DAISY_SECRET_KEY`.\n\n```txt\n# Example values\nDAISY_OTP_ID=plantae\nDAISY_OTP_SECRET_KEY=key\n```\n\n#### 1.2 Server integration\n\nCreate an instance of `ServerPayments` from the `@daisypayments/daisy-sdk/private` sub-module.\nIt is extremely important to keep `DAISY_OTP_SECRET_KEY` **private**.\n\n```js\nconst DaisySDK = require(\"@daisypayments/daisy-sdk/private\");\nconst fetch = require(\"node-fetch\");\n\nconst payments = new DaisySDK.ServerPayments({\n  manager: {\n    identifier: process.env.DAISY_OTP_ID,\n    secretKey: process.env.DAISY_OTP_SECRET_KEY,\n  },\n  withGlobals: { fetch },\n});\n```\n\n> Server instances requires an instance of `fetch`. We recommend [node-fetch](https://www.npmjs.com/package/node-fetch).\n\nLet's say we want to sell an access pass for 20 USD or equivalent in DAI.\n\n```js\nconst express = require(\"express\");\nconst h = require(\"express-async-handler\");\n\nconst app = express();\n\napp.get(\"/api/checkout/invoice/\", h(async (req, res) => {\n  const user = req.session;\n\n  // Create an invoice using Daisy SDK\n  const invoice = await payments.createInvoice({\n    invoicedPrice: 20, // required\n    invoicedEmail: user.email, // optional\n    invoicedName: user.name, // optional\n    invoicedDetail: \"Paid Access\", // optional\n  });\n\n  // Save and associate invoice to user\n  await user.update({ invoiceId: invoice[\"id\"]} );\n\n  // Use this object in the frontend to start the transaction.\n  res.json({ invoice });\n});\n```\n\nThe `invoice` object looks like this using TypeScript notation:\n\n```ts\ninterface PaymentInvoice {\n  id: string;\n  identifier: string;\n  state: PaymentInvoiceState;\n  amountPaid: string | BigNumber;\n  paidAt?: string;\n  address: string;\n  tokenAddress: string;\n  walletAddress: string;\n  invoicedPrice: string;\n  invoicedEmail?: string;\n  invoicedName?: string;\n  invoicedDetail?: string;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n\nexport enum PaymentInvoiceState {\n  Pending = \"PENDING\",\n  UnderPaid = \"UNDER_PAID\",\n  Paid = \"PAID\",\n  OverPaid = \"OVER_PAID\",\n}\n```\n\nSince any transaction sending money to the invoice address can fulfill the requested amount, one way to know the state of the payment is to ask Daisy via polling.\n\n```js\napp.get(\"/api/checkout/state/\", h(async (req, res) => {\n  const user = req.session;\n\n  try {\n    const invoice = await payments.getInvoice({\n      identifier: user.invoiceId,\n    });\n    const success = [\"PAID\", \"OVER_PAID\"].includes(invoice[\"state\"]);\n\n    res.json({ invoice });\n  } catch (error) {\n    //\n  }\n});\n```\n\nTo get the receipts from any Invoice:\n\n```js\nconst receipts = await payments.getReceipts({\n  identifier: user.invoiceId,\n});\n```\n\nReceipt object shape:\n\n```ts\ninterface PaymentReceipt {\n  id: string;\n  txHash: string;\n  account: string;\n  amount: string | BigNumber;\n  onChainCreatedAt: string | Date;\n  createdAt: string | Date;\n  updatedAt: string | Date;\n}\n```\n","readmeFilename":"README.md"}