{"id":15344976,"url":"https://github.com/elek/easypin","last_synced_at":"2025-04-14T23:36:16.002Z","repository":{"id":43148062,"uuid":"467042096","full_name":"elek/easypin","owner":"elek","description":"Smart-contract based IPFS service based on STORJ backend","archived":false,"fork":false,"pushed_at":"2022-03-18T08:25:02.000Z","size":13230,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T11:42:43.567Z","etag":null,"topics":["decentralized","ipfs","storage","storj"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-07T10:15:08.000Z","updated_at":"2023-11-05T10:21:51.000Z","dependencies_parsed_at":"2022-07-22T00:29:59.428Z","dependency_job_id":null,"html_url":"https://github.com/elek/easypin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elek%2Feasypin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elek%2Feasypin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elek%2Feasypin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elek%2Feasypin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elek","download_url":"https://codeload.github.com/elek/easypin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248980708,"owners_count":21193136,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decentralized","ipfs","storage","storj"],"created_at":"2024-10-01T11:07:46.379Z","updated_at":"2025-04-14T23:36:15.980Z","avatar_url":"https://github.com/elek.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Easypin is a IPFS pinning service governed by a smart-contract, backed by [Storj](https://storj.io) decentralized\nstorage.\n\n\u003c!--ts--\u003e\n* [Overview](#overview)\n* [What it does](#what-it-does)\n* [Getting started](#getting-started)\n   * [Request pinning via browser / metamask](#request-pinning-via-browser--metamask)\n   * [Request pinning from NFT contract (example)](#request-pinning-from-nft-contract-example)\n* [Deployments](#deployments)\n   * [Rinkeby deployment](#rinkeby-deployment)\n* [Development](#development)\n   * [Local deployment](#local-deployment)\n      * [Generate two accounts](#generate-two-accounts)\n      * [Deploy GOLD token (key1)](#deploy-gold-token-key1)\n      * [Deploy FAUCET (key1)](#deploy-faucet-key1)\n      * [Self-request token (key2)](#self-request-token-key2)\n      * [Deploy the pin contract (key1)](#deploy-the-pin-contract-key1)\n      * [Use the pin contract (key2)](#use-the-pin-contract-key2)\n      * [Starting the API server:](#starting-the-api-server)\n   * [Web development](#web-development)\n\n\u003c!-- Added by: elek, at: Fri Mar 18 09:24:26 AM CET 2022 --\u003e\n\n\u003c!--te--\u003e\n\nEasypin service has the following components:\n\n * A smart contract which records the pinning request (see `./contract`)\n * An off-chain backend service which takes care about the pinning\n * A web-ui which makes easier to request new pinnings (using metamask)\n\nThe project is created by Kaloyan Raev, Marton Elek and Michael Ferris for [Faber Web3 hackathon](https://faberweb3.devpost.com/):\n\nMore details can be found here:\n\nhttps://devpost.com/software/crowdpinning-on-ipfs-using-decentralized-object-storage\n\n# Overview\n\nWeb3 promises to be decentralized, trustless, permissionless, and autonomous technology. A glance at the current popular IPFS pinning services shows that they still stick to the traditional way of doing things:\n* They require you to register an account and pay with a credit card.\n* They store the pinned data on centralized cloud storage.\n* They require you to trust them they will do what they have promised.\n\nThis project aims to provide an alternative, more Web3-oriented approach:\n* No need to register an account or obtain API keys.\n* Pay with crypto on the blockchain.\n* Store the pinned content on decentralized storage.\n* Verify on the blockchain that a specific IPFS hash has been requested to pin for a specific period.\n* Optionally, smart contracts can use this pinning approach, e.g. during NFT minting.\n\n# What it does\n\nThe project uses [Storj](https://www.storj.io/) for storing the pinned content. Storj is decentralized object storage that splits the content into small encrypted pieces and stores them on tens of thousands of nodes across the globe. The project uses the [Storj datastore for IPFS](https://github.com/kaloyan-raev/ipfs-go-ds-storj) to store the IPFS blocks in a Storj bucket.\n\nStorj has its ERC-20 utility token called [STORJ](https://www.coingecko.com/en/coins/storj). Storage node operators receive STORJ for their service for storing and serving pieces of the data. Users who store data on the Storj network use the token to pay for the service.\n\nA key component of the project is an [Ethereum smart contract](https://rinkeby.etherscan.io/address/0xe7b556AB490C931dcc3319B56fC83B0628AE21bb) with a method:\n\n    pin(ipfsHash, tokenAmount)\n\nThis method allows users and Dapps to deposit a specific amount of STORJ for a specific IPFS hash. (some additional parameters can flag if descriptor is supposed to be parsed during the pinning)\n\nThe pinning service listens for events from the smart contract and pins the IPFS hash to an IPFS cluster backed by the Storj datastore. The pinning period is calculated from the content size and the STORJ amount deposited. This period can be extended by sending another transaction to the smart contract for the same IPFS hash. By anyone who is interested in keeping the content for longer in the IPFS network.\n\nThe pinning service provides a restricted IPFS gateway. \"Restricted\" means that it will serve only the data that is pinned on the IPFS nodes of the service’s cluster. This IPFS gateway can be used as proof that the IPFS hash is really pinned by the service. The gateway is also the fastest way to retrieve the pinned content back from the IPFS network.\n\nThe project is currently [demonstrated](https://easypin.storj-ipfs.com) on the Rinkeby Testnet. It can be deployed on any EVM-compatible blockchain like Ethereum Mainnet, Polygon, Avalanche, zkSync 2.0, etc. Some of these blockchains maintain low gas fees, which makes the micropayments for pinning IPFS hashes feasible with this smart contract.\n\n![Architecture](./overview.png)\n\n# Getting started\n\nSmart contract function is deployed on rinkeby testnet and can be called via the web-ui or from any contract (eg. from an NFT contract).\n\n## Request pinning via browser / metamask\n\n* Rinkeby web UI can be found here: https://easypin.storj-ipfs.com/#/\n* To getting started you can watch the [quick demonstration video](https://www.youtube.com/watch?v=imdNFsP0NWA) how to use it.\n\n## Request pinning from NFT contract (example)\n\nAn example NFT contract can be found in `test/NFT.sol`.\n\nTo use it:\n\n1. Deploy the NFT contract (assuming PIN contract is already deployed)\n\n```\ncethacea contract deploy https://github.com/elek/cethacea '(address)' PIN\n```\n\n2. Upload the image to IPFS:\n\n```\ncurl -v -X POST -F file=@overview.png https://$YOUR_DOMAIN/api/v0/add\n```\n\n3. Update the hash in `test/nft.json`:\n\n```\n{\n  \"description\": \"A very nice NFT pinned directly from a contract\",\n  \"image\": \"ipfs://QmT5beRZQRDV5m9NaS65g8rzRXJmvjKtnUR6pabjFty8ao\",\n  \"name\": \"Item\"\n}\n```\n\n4. Upload descriptor to IPFS\n\n```\ncurl -v -X POST -F file=@test/nft.json https://$YOUR_DOMAIN/api/v0/add\n```\n\n5. Mint a new NFT with calling the NFT smart contract:\n\n```\ncethacea contract call --contract STORJ approve PIN 100000000000\nceth contract call --contract NFT mintNew 0x712Ce0cBEe9423E414493542FfebF418C16c1C96 QmYG8LGb24nsNHbKgqmWLWXT5ha3cZuooFXEC4Cw1tVTvw\n```\n\n\n# Deployments\n\n## Rinkeby deployment\n\nRinkeby deployment uses the ZkSync Test STORJ tokens. You can mint\nit [here](https://wallet.zksync.io/?network=rinkeby) (Add Funds, Mint tokens, ....)\n\nToken (ZkSync test STORJ token)\ncontract [0x8098165d982765097e4aa17138816e5b95f9fdb5](https://rinkeby.etherscan.io/address/0x8098165d982765097e4aa17138816e5b95f9fdb5)\n\nTokens can be requested via the faucet of ZkSync wallet (https://wallet.zksync.io/?network=rinkeby / Add Funds / Mint tokens) \n\nPIN\ncontract: [0xe7b556AB490C931dcc3319B56fC83B0628AE21bb](https://rinkeby.etherscan.io/address/0xe7b556AB490C931dcc3319B56fC83B0628AE21bb)\n\nDeployed with:\n\n```\ncethacea c deploy --name PIN --abi ../contract/StorjPin.abi ../contract/StorjPin.bin '(address)' STORJ \n```\n\n# Development\n\n## Local deployment\n\nYou can deploy all the contracts with the help of [cethacea](https://github.com/elek/cethacea):\n\n### Generate two accounts\n\n```\ncethacea account generate\ncethacea account generate\n```\n\n### Deploy GOLD token (key1)\n\n```\ncethacea contract deploy --account key1 --name GOLD --abi test/Gold.abi test/Gold.bin\ncethacea token balance --account key1 --contract GOLD\n```\n\n### Deploy FAUCET (key1)\n\n```\ncethacea contract deploy --account key1 --name FAUCET --abi test/Faucet.abi test/Faucet.bin '(address)' GOLD \ncethacea token transfer --contract GOLD --account key1 100000000000000000000 FAUCET \ncethacea token balance --account key1 --contract GOLD FAUCET\ncethacea token balance --account key1 --contract GOLD key1\n\n```\n\n### Self-request token (key2)\n\n```\ncethacea contract call --account key2 --contract FAUCET 'get()'\ncethacea token balance --contract GOLD key2\n```\n\n### Deploy the pin contract (key1)\n\n```\ncethacea contract deploy --account key1 --name PIN --abi StorjPin.abi StorjPin.bin '(address)' GOLD\n```\n\n### Use the pin contract (key2)\n\n```\ncethacea contract call --account key2 --contract GOLD approve PIN 10000000000000000000000 \ncethacea contract call --account key2 --contract PIN pin 'QmcUkP3BMDkKNp2V6FTojXqgCMWdpDFQb74uphQVdWpi9Z' 100000000000000000\ncethacea log --contract PIN\n```\n\n### Starting the API server:\n\n```\ngo run ./cmd/easypin/main.go \\\n   --crypto.ethereum-endpoint==https://mainnet.infura.io/v3/PROJECT_ID \\\n   --crypto.pin-contract=0xe7b556AB490C931dcc3319B56fC83B0628AE21bb \\\n   --crypto.token-contract=0x8098165d982765097e4aa17138816e5b95f9fdb5 \\\n   --database 'postgres://root@sd:26257/pin?sslmode=disable' \\\n   --api.address 127.0.0.1:8787\n   --ipfs.address /ip4/127.0.0.1/tcp/5001\n```\n\nRequirements:\n\n 1. Working ethereum node where contracts are deployed (you can use infura rinkeby URL or a local chain from `./testchain`)\n 2. Cockroach (or postgres). Please create the scheme (`pin` in our example)\n 3. Running IPFS node (`ipfs daemon`) \n\n## Web development\n\nDeveloper version (proxy is activated for `/api/*` to proxy requests to `127.0.0.1:8787`: it requires running go lang instance ):\n\n```\ncd web\nnpm install\nnpx vite\n```\n\nProduction version:\n\n```\ncd web\nnpx vite build\n```\n\nIt saves the final artifacts to `web/dist` which is exposed by the golang api.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felek%2Feasypin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felek%2Feasypin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felek%2Feasypin/lists"}