{"id":28661998,"url":"https://github.com/diva-exchange/i2p-sam","last_synced_at":"2025-06-13T11:07:00.568Z","repository":{"id":45266338,"uuid":"428688668","full_name":"diva-exchange/i2p-sam","owner":"diva-exchange","description":"I2P SAM: peer-to-peer communication between applications over I2P","archived":false,"fork":false,"pushed_at":"2025-05-13T20:03:27.000Z","size":722,"stargazers_count":16,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-05-13T21:02:43.672Z","etag":null,"topics":["crypto","diva","i2p","p2p","peer-to-peer","sam"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/diva-exchange.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-11-16T14:29:05.000Z","updated_at":"2025-05-13T19:55:34.000Z","dependencies_parsed_at":"2024-06-18T22:41:06.391Z","dependency_job_id":"4bc65a8b-28bd-4c7e-8f1c-e0d5dbedc84e","html_url":"https://github.com/diva-exchange/i2p-sam","commit_stats":{"total_commits":74,"total_committers":3,"mean_commits":"24.666666666666668","dds":0.2702702702702703,"last_synced_commit":"65e6da8679caacf4d2dd0597c0048556a760960f"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/diva-exchange/i2p-sam","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diva-exchange%2Fi2p-sam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diva-exchange%2Fi2p-sam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diva-exchange%2Fi2p-sam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diva-exchange%2Fi2p-sam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/diva-exchange","download_url":"https://codeload.github.com/diva-exchange/i2p-sam/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/diva-exchange%2Fi2p-sam/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259634349,"owners_count":22887697,"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":["crypto","diva","i2p","p2p","peer-to-peer","sam"],"created_at":"2025-06-13T11:01:56.960Z","updated_at":"2025-06-13T11:07:00.551Z","avatar_url":"https://github.com/diva-exchange.png","language":"TypeScript","funding_links":[],"categories":["Libraries"],"sub_categories":["SAM"],"readme":"# I2P SAM\nAn I2P SAM library: enabling applications to communicate through the I2P network. \n\nLong story short: I2P is an anonymous network layer allowing censorship-resistant and end-to-end-encrypted communication. I2P is a fully distributed, \"privacy-by-design\" peer-to-peer network.\n\nTo get I2P up and running, take a look at the project: https://github.com/diva-exchange/i2p\n\n## Use Cases\nI2P is an instantly available peer-to-peer network which can be used for things like:\n* chat, social media and alike - all private and secure\n* distributed databases, aka blockchains (see https://testnet.diva.exchange as an example)\n* gaming, file sharing and ... whatever else you come up with\n\nI2P is fully distributed, well researched and gets further developed by a competent community.\n\nThis I2P SAM library helps developers to create an I2P application quickly and hassle-free.  \n\n## Get Started\n\n`npm i @diva.exchange/i2p-sam`\n\nor, lighter, without developer dependencies:\n\n`npm i --omit dev @diva.exchange/i2p-sam`\n\n## Quick Start - Examples\n\n### How to Use Streams\n\nSend an HTTP GET request to diva.i2p and output the response:\n\n```\nimport { createStream } from '@diva.exchange/i2p-sam';\n\n(async () =\u003e {\n\n  const s = await createStream({\n    stream: {\n      destination: 'diva.i2p'\n    },\n    sam: {\n      // your local I2P SAM host,\n      // like 172.19.74.11 if you use the given test\n      // docker container (see \"Unit Tests\" below)\n      host: '127.0.0.1',\n      // your local I2P SAM port, this is the default\n      portTCP: 7656\n    },\n  });\n  s.on('data', (data: Buffer) =\u003e {\n    console.log('Incoming Data: ' + data.toString());\n  });\n  \n  s.stream(Buffer.from('GET /hosts.txt HTTP/1.1\\r\\nHost: diva.i2p\\r\\n\\r\\n'));\n\n})();\n```\n\nForward incoming streaming data to a local socket server:\n\n```\nimport { createStream, createForward, I2pSamStream } from '@diva.exchange/i2p-sam';\nimport net from 'net';\n\n(async () =\u003e {\n  const serverForward = net.createServer((c) =\u003e {\n    console.debug('client connected');\n    c.on('end', () =\u003e {\n      console.debug('client disconnected');\n    });\n    c.on('data', (data: Buffer) =\u003e {\n      console.debug(data.toString());\n      c.write(`Hello Client!\\n`);\n    });\n  });\n  serverForward.listen(20222, '127.0.0.2');\n\n  const samForward: I2pSamStream = await createForward({\n    sam: { \n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    },\n    forward: {\n      host: '127.0.0.2',  // your local listener, see above\n      port: 20222,        // your local listener, see above\n    },\n  });\n\n  const samClient: I2pSamStream = await createStream({\n    sam: { \n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    },\n    stream: {\n      destination: samForward.getPublicKey()\n    },\n  });\n  // event handler\n  samClient.on('data', (data: Buffer) =\u003e {\n    console.debug(data.toString());\n  });\n  // send some data to destination\n  samClient.stream(Buffer.from(`Hi Server!\\n`));\n})();\n```\n\n### How to Use Reply-able Datagrams\n\nNOTE: reply-able datagrams contain the origin of the data. An \"origin\" is defined as the public key of a node in the I2P network. \n\nSend reply-able UDP messages from peer **A** to peer **B** through the I2P network:\n\n```\nimport { createDatagram, toB32 } from '@diva.exchange/i2p-sam';\n\n(async () =\u003e {\n  // instantiate Peer A\n  const peerA = await createDatagram({\n    sam: {\n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    }\n  }); \n  \n  // instantiate Peer B\n  const peerB = await createDatagram({\n    sam: {\n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    },\n    listen: { \n      address: '127.0.0.1',  // udp listener\n      port: 20202            // udp listener\n    }\n  }).on('data', (data: Buffer, from) =\u003e {\n    console.debug(`Incoming Data from ${toB32(from)}: ${data.toString()}`);\n  });\n\n    \n  // send 100 messages via UDP, every 500ms a message\n  // IMPORTANT: UDP is not reliable. Some messages might get lost.\n  const msg: string = 'Hello World';\n  await new Promise((resolve) =\u003e {\n    let t = 0;\n    const i = setInterval(() =\u003e {\n      peerA.send(peerB.getPublicKey(), Buffer.from(`${t} ${msg}`));\n      if (t++ \u003e= 100) {\n        clearInterval(i);\n        resolve(true);\n      }\n    }, 500);\n  });\n})();\n```\n\n### How to Use Raw Datagrams\n\nNOTE: raw datagrams do not contain the \"origin\" of the data. A typical use case for raw datagrams: broadcasting of data. Raw datagrams are lean.\n\nSend raw UDP messages from peer **A** to peer **B** through the I2P network:\n\n```\nimport { createRaw } from '@diva.exchange/i2p-sam';\n\n(async () =\u003e {\n  // instantiate Peer A\n  const peerA = await createRaw({\n    sam: {\n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    }\n  }); \n  \n  // instantiate Peer B\n  const peerB = await createRaw({\n    sam: {\n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    },\n    listen: { \n      address: '127.0.0.1',  // udp listener\n      port: 20202            // udp listener\n    }\n  }).on('data', (data: Buffer) =\u003e {\n    console.log('Incoming Data: ' + data.toString());\n  });\n\n  // send 100 messages via UDP, every 500ms a message\n  // IMPORTANT: UDP is not reliable. Some messages might get lost.\n  const msg: string = 'Hello Peer B - I am Peer A';\n  await new Promise((resolve) =\u003e {\n    let t = 0;\n    const i = setInterval(() =\u003e {\n      peerA.send(peerB.getPublicKey(), Buffer.from(`${t} ${msg}`));\n      if (t++ \u003e= 100) {\n        clearInterval(i);\n        resolve(true);\n      }\n    }, 500);\n  });\n})();\n```\n\n## API\n\n### getPublicKey(): string\n\nGet the public key of the local destination.\n\nExample: \n\n```\nimport { createDatagram } from '@diva.exchange/i2p-sam';\n\ncreateDatagram({\n  sam: {\n    host: '127.0.0.1',  // your local I2P SAM host\n    portTCP: 7656       // your local I2P SAM port\n  }\n}).then((sam) =\u003e console.log(sam.getPublicKey()));\n```\n\n### getPrivateKey(): string\n\nGet the private key of the local destination.\n\nExample: \n\n```\nimport { createDatagram } from '@diva.exchange/i2p-sam';\n\ncreateDatagram({\n  sam: {\n    host: '127.0.0.1',  // your local I2P SAM host\n    portTCP: 7656       // your local I2P SAM port\n  }\n}).then((sam) =\u003e console.log(sam.getPrivateKey()));\n```\n\n### getKeyPair(): { public: string, private: string }\n\nGet the public and private key of the local destination.\n\nExample: \n\n```\nimport { createStream } from '@diva.exchange/i2p-sam';\n\ncreateStream({\n  sam: {\n    host: '127.0.0.1',  // your local I2P SAM host\n    portTCP: 7656       // your local I2P SAM port\n  },\n  stream: {\n    destination: 'diva.i2p'\n  },\n}).then((sam) =\u003e console.log(sam.getKeyPair()));\n```\n\n### close()\n\nClose a SAM connection.\n\nExample: \n\n```\nimport { createRaw } from '@diva.exchange/i2p-sam';\n\n(async () =\u003e {\n  const sam = await createRaw({\n    sam: {\n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    }\n  });\n  \n  sam.close();\n})();\n```\n\n### toB32(destination: string): string\n\nConvert a destination to a b32 address (without any extensions - just a Base32 string).\n\nExample: \n\n```\nimport { toB32 } from '@diva.exchange/i2p-sam';\n\nconsole.log(toB32('[some base64-encoded destination]'));\n```\n\n### createLocalDestination(c: Configuration): Promise\\\u003c{ address: string, public: string, private: string }\\\u003e\n\nCreate a new local destination and return its properties.\n\nExample: \n\n```\nimport { createLocalDestination } from '@diva.exchange/i2p-sam';\n\ncreateLocalDestination({\n  sam: {\n    host: '127.0.0.1',  // your local I2P SAM host\n    portTCP: 7656       // your local I2P SAM port\n  }\n}).then((obj) =\u003e console.log(obj));\n```\n\n\n### lookup(c: Configuration, name: string): Promise\\\u003cstring\\\u003e\n\nLookup (aka resolve) an I2P address (like diva.i2p or also a .b32.i2p address) to a destination. The destination, which is the public key, is a base64 encoded string.\n\nExample: \n\n```\nimport { lookup } from '@diva.exchange/i2p-sam';\n\nlookup({\n  sam: {\n    host: '127.0.0.1',  // your local I2P SAM host\n    portTCP: 7656       // your local I2P SAM port\n  }\n}, 'diva.i2p').then((dest) =\u003e console.log(dest));\n```\n\n### stream(msg: Buffer)\n\nExample: see the _Get Started: How to Use Streams_ above. \n\n\n### send(destination: string, msg: Buffer)\n\nExample: see _Get Started: How to Use Datagrams_ above. \n\n### Configuration and its Defaults\n```\ntype tSession = {\n  id?: string;\n  options?: string;\n};\n\ntype tStream = {\n  destination: string;\n};\n\ntype tForward = {\n  host: string;\n  port: number;\n  silent?: boolean;\n};\n\ntype tListen = {\n  address: string;\n  port: number;\n  hostForward?: string;\n  portForward?: number;\n};\n\ntype tSam = {\n  host: string;\n  portTCP: number;\n  portUDP?: number;\n  versionMin?: string;\n  versionMax?: string;\n  publicKey?: string;\n  privateKey?: string;\n  timeout?: number;\n};\n\nexport type Configuration = {\n  session?: tSession;\n  stream?: tStream;\n  forward?: tForward;\n  listen?: tListen;\n  sam?: tSam;\n};\n\ntype ConfigurationDefault = {\n  session: tSession;\n  stream: tStream;\n  forward: tForward;\n  listen: tListen;\n  sam: tSam;\n};\n\nconst DEFAULT_CONFIGURATION: ConfigurationDefault = {\n  session: {\n    id: '',\n    options: '',\n  },\n  stream: {\n    destination: '',\n  },\n  forward: {\n    host: '',\n    port: 0,\n    silent: false,\n  },\n  listen: {\n    address: '127.0.0.1',\n    port: 0,\n    hostForward: '',\n    portForward: 0,\n  },\n  sam: {\n    host: '127.0.0.1',\n    portTCP: 7656,\n    portUDP: 7655,\n    versionMin: '',\n    versionMax: '',\n    publicKey: '',\n    privateKey: '',\n    timeout: 300,\n  },\n};\n```\n\n### Events\n\n#### data\nIncoming data.\n\n#### error\nGeneric Error event - emitted if sockets report errors.\n\n```\nimport { createRaw } from '@diva.exchange/i2p-sam';\n\n(async () =\u003e {\n  const sam = await createRaw({\n    sam: {\n      host: '127.0.0.1',  // your local I2P SAM host\n      portTCP: 7656       // your local I2P SAM port\n    }\n  });\n  sam.on('error', (error) =\u003e console.debug(error));\n})();\n```\n\n#### close\nEmitted if one of the involved sockets got closed.  \n\n\n## How to Run Unit Tests\n\nAssumptions: \n1. git, node and npm is available. \n2. docker and docker-compose is available. \n\nClone the source code from git `git clone https://github.com/diva-exchange/i2p-sam.git` and enter the folder `i2p-sam`.\n\nPrepare the test environment by creating the docker container:\n\n```\ndocker compose -f test/sam.diva.i2p.yml up -d\n```\n\nCheck whether the I2P test node is properly running by accessing the local console on: http://172.19.74.11:7070.\n\nTo modify the IP address of the local console, adapt the file `test/sam.diva.i2p.yml`.\n\nAfter the docker container is _running for about five minutes_ (reason: the I2P network needs some minutes to integrate), execute the unit tests:\n\n```\nnpm run test\n```\nExecuting the unit tests will take around 5 minutes. Reason: the communication via I2P gets tested - which is the purpose of this library.\n\nStop the container (and purge all data within):\n```\ndocker compose -f test/sam.diva.i2p.yml down --volumes\n```\n \n\n## Linting\n\nTo lint the code, use\n```\nnpm run lint\n```\n\n## Contributions\nContributions are very welcome. This is the general workflow:\n\n1. Fork from https://github.com/diva-exchange/divachain/\n2. Pull the forked project to your local developer environment\n3. Make your changes, test, commit and push them\n4. Create a new pull request on github.com\n\nIt is strongly recommended to sign your commits: https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key\n\nIf you have questions, please just contact us (see below).\n\n## Donations\n\nYour donation goes entirely to the project. Your donation makes the development of DIVA.EXCHANGE faster. Thanks a lot.\n\n### XMR\n\n42QLvHvkc9bahHadQfEzuJJx4ZHnGhQzBXa8C9H3c472diEvVRzevwpN7VAUpCPePCiDhehH4BAWh8kYicoSxpusMmhfwgx\n\n![XMR](https://www.diva.exchange/wp-content/uploads/2020/06/diva-exchange-monero-qr-code-1.jpg)\n\nor via https://www.diva.exchange/en/join-in/\n\n### BTC\n\n3Ebuzhsbs6DrUQuwvMu722LhD8cNfhG1gs\n\n![BTC](https://www.diva.exchange/wp-content/uploads/2020/06/diva-exchange-bitcoin-qr-code-1.jpg)\n\n## Contact the Developers\n\nOn [DIVA.EXCHANGE](https://www.diva.exchange) you'll find various options to get in touch with the team.\n\nTalk to us via [Telegram](https://t.me/diva_exchange_chat_de) (English or German).\n\n## References\n\nSAM docs: https://geti2p.net/en/docs/api/samv3\n\nI2Pd: https://i2pd.readthedocs.io/\n\n## License\n\n[APACHE 2.0](https://github.com/diva-exchange/i2p-sam/blob/main/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiva-exchange%2Fi2p-sam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdiva-exchange%2Fi2p-sam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiva-exchange%2Fi2p-sam/lists"}