
Security News
Scaling Socket from Zero to 10,000+ Organizations
Socket CEO Feross Aboukhadijeh shares lessons from scaling a developer security startup to 10,000+ organizations in this founder interview.
@diva.exchange/i2p-sam
Advanced tools
I2P SAM: peer-to-peer communication between applications over I2P
An I2P SAM library: enabling applications to communicate through the I2P network.
Long 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.
To get I2P up and running, take a look at the project: https://github.com/diva-exchange/i2p
I2P is an instantly available peer-to-peer network which can be used for things like:
I2P is fully distributed, well researched and gets further developed by a competent community.
This I2P SAM library helps developers to create an I2P application quickly and hassle-free.
npm i @diva.exchange/i2p-sam
or, lighter, without developer dependencies:
npm i --omit dev @diva.exchange/i2p-sam
Send an HTTP GET request to diva.i2p and output the response:
import { createStream } from '@diva.exchange/i2p-sam';
(async () => {
const s = await createStream({
stream: {
destination: 'diva.i2p'
},
sam: {
// your local I2P SAM host,
// like 172.19.74.11 if you use the given test
// docker container (see "Unit Tests" below)
host: '127.0.0.1',
// your local I2P SAM port, this is the default
portTCP: 7656
},
});
s.on('data', (data: Buffer) => {
console.log('Incoming Data: ' + data.toString());
});
s.stream(Buffer.from('GET /hosts.txt HTTP/1.1\r\nHost: diva.i2p\r\n\r\n'));
})();
Forward incoming streaming data to a local socket server:
import { createStream, createForward, I2pSamStream } from '@diva.exchange/i2p-sam';
import net from 'net';
(async () => {
const serverForward = net.createServer((c) => {
console.debug('client connected');
c.on('end', () => {
console.debug('client disconnected');
});
c.on('data', (data: Buffer) => {
console.debug(data.toString());
c.write(`Hello Client!\n`);
});
});
serverForward.listen(20222, '127.0.0.2');
const samForward: I2pSamStream = await createForward({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
},
forward: {
host: '127.0.0.2', // your local listener, see above
port: 20222, // your local listener, see above
},
});
const samClient: I2pSamStream = await createStream({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
},
stream: {
destination: samForward.getPublicKey()
},
});
// event handler
samClient.on('data', (data: Buffer) => {
console.debug(data.toString());
});
// send some data to destination
samClient.stream(Buffer.from(`Hi Server!\n`));
})();
NOTE: reply-able datagrams contain the origin of the data. An "origin" is defined as the public key of a node in the I2P network.
Send reply-able UDP messages from peer A to peer B through the I2P network:
import { createDatagram, toB32 } from '@diva.exchange/i2p-sam';
(async () => {
// instantiate Peer A
const peerA = await createDatagram({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
});
// instantiate Peer B
const peerB = await createDatagram({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
},
listen: {
address: '127.0.0.1', // udp listener
port: 20202 // udp listener
}
}).on('data', (data: Buffer, from) => {
console.debug(`Incoming Data from ${toB32(from)}: ${data.toString()}`);
});
// send 100 messages via UDP, every 500ms a message
// IMPORTANT: UDP is not reliable. Some messages might get lost.
const msg: string = 'Hello World';
await new Promise((resolve) => {
let t = 0;
const i = setInterval(() => {
peerA.send(peerB.getPublicKey(), Buffer.from(`${t} ${msg}`));
if (t++ >= 100) {
clearInterval(i);
resolve(true);
}
}, 500);
});
})();
NOTE: raw datagrams do not contain the "origin" of the data. A typical use case for raw datagrams: broadcasting of data. Raw datagrams are lean.
Send raw UDP messages from peer A to peer B through the I2P network:
import { createRaw } from '@diva.exchange/i2p-sam';
(async () => {
// instantiate Peer A
const peerA = await createRaw({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
});
// instantiate Peer B
const peerB = await createRaw({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
},
listen: {
address: '127.0.0.1', // udp listener
port: 20202 // udp listener
}
}).on('data', (data: Buffer) => {
console.log('Incoming Data: ' + data.toString());
});
// send 100 messages via UDP, every 500ms a message
// IMPORTANT: UDP is not reliable. Some messages might get lost.
const msg: string = 'Hello Peer B - I am Peer A';
await new Promise((resolve) => {
let t = 0;
const i = setInterval(() => {
peerA.send(peerB.getPublicKey(), Buffer.from(`${t} ${msg}`));
if (t++ >= 100) {
clearInterval(i);
resolve(true);
}
}, 500);
});
})();
Get the public key of the local destination.
Example:
import { createDatagram } from '@diva.exchange/i2p-sam';
createDatagram({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
}).then((sam) => console.log(sam.getPublicKey()));
Get the private key of the local destination.
Example:
import { createDatagram } from '@diva.exchange/i2p-sam';
createDatagram({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
}).then((sam) => console.log(sam.getPrivateKey()));
Get the public and private key of the local destination.
Example:
import { createStream } from '@diva.exchange/i2p-sam';
createStream({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
},
stream: {
destination: 'diva.i2p'
},
}).then((sam) => console.log(sam.getKeyPair()));
Close a SAM connection.
Example:
import { createRaw } from '@diva.exchange/i2p-sam';
(async () => {
const sam = await createRaw({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
});
sam.close();
})();
Convert a destination to a b32 address (without any extensions - just a Base32 string).
Example:
import { toB32 } from '@diva.exchange/i2p-sam';
console.log(toB32('[some base64-encoded destination]'));
Create a new local destination and return its properties.
Example:
import { createLocalDestination } from '@diva.exchange/i2p-sam';
createLocalDestination({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
}).then((obj) => console.log(obj));
Lookup (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.
Example:
import { lookup } from '@diva.exchange/i2p-sam';
lookup({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
}, 'diva.i2p').then((dest) => console.log(dest));
Example: see the Get Started: How to Use Streams above.
Example: see Get Started: How to Use Datagrams above.
type tSession = {
id?: string;
options?: string;
};
type tStream = {
destination: string;
};
type tForward = {
host: string;
port: number;
silent?: boolean;
};
type tListen = {
address: string;
port: number;
hostForward?: string;
portForward?: number;
};
type tSam = {
host: string;
portTCP: number;
portUDP?: number;
versionMin?: string;
versionMax?: string;
publicKey?: string;
privateKey?: string;
timeout?: number;
};
export type Configuration = {
session?: tSession;
stream?: tStream;
forward?: tForward;
listen?: tListen;
sam?: tSam;
};
type ConfigurationDefault = {
session: tSession;
stream: tStream;
forward: tForward;
listen: tListen;
sam: tSam;
};
const DEFAULT_CONFIGURATION: ConfigurationDefault = {
session: {
id: '',
options: '',
},
stream: {
destination: '',
},
forward: {
host: '',
port: 0,
silent: false,
},
listen: {
address: '127.0.0.1',
port: 0,
hostForward: '',
portForward: 0,
},
sam: {
host: '127.0.0.1',
portTCP: 7656,
portUDP: 7655,
versionMin: '',
versionMax: '',
publicKey: '',
privateKey: '',
timeout: 300,
},
};
Incoming data.
Generic Error event - emitted if sockets report errors.
import { createRaw } from '@diva.exchange/i2p-sam';
(async () => {
const sam = await createRaw({
sam: {
host: '127.0.0.1', // your local I2P SAM host
portTCP: 7656 // your local I2P SAM port
}
});
sam.on('error', (error) => console.debug(error));
})();
Emitted if one of the involved sockets got closed.
Assumptions:
Clone the source code from git git clone https://github.com/diva-exchange/i2p-sam.git and enter the folder i2p-sam.
Prepare the test environment by creating the docker container:
docker compose -f test/sam.diva.i2p.yml up -d
Check whether the I2P test node is properly running by accessing the local console on: http://172.19.74.11:7070.
To modify the IP address of the local console, adapt the file test/sam.diva.i2p.yml.
After the docker container is running for about five minutes (reason: the I2P network needs some minutes to integrate), execute the unit tests:
npm run test
Executing the unit tests will take around 5 minutes. Reason: the communication via I2P gets tested - which is the purpose of this library.
Stop the container (and purge all data within):
docker compose -f test/sam.diva.i2p.yml down --volumes
To lint the code, use
npm run lint
Contributions are very welcome. This is the general workflow:
It is strongly recommended to sign your commits: https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key
If you have questions, please just contact us (see below).
Your donation goes entirely to the project. Your donation makes the development of DIVA.EXCHANGE faster. Thanks a lot.
42QLvHvkc9bahHadQfEzuJJx4ZHnGhQzBXa8C9H3c472diEvVRzevwpN7VAUpCPePCiDhehH4BAWh8kYicoSxpusMmhfwgx

or via https://www.diva.exchange/en/join-in/
3Ebuzhsbs6DrUQuwvMu722LhD8cNfhG1gs

On DIVA.EXCHANGE you'll find various options to get in touch with the team.
Talk to us via Telegram (English or German).
SAM docs: https://geti2p.net/en/docs/api/samv3
I2Pd: https://i2pd.readthedocs.io/
FAQs
I2P SAM: peer-to-peer communication between applications over I2P
We found that @diva.exchange/i2p-sam demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh shares lessons from scaling a developer security startup to 10,000+ organizations in this founder interview.

Research
Socket Threat Research maps a rare inside look at OtterCookie’s npm-Vercel-GitHub chain, adding 197 malicious packages and evidence of North Korean operators.

Research
Socket researchers identified a malicious Chrome extension that manipulates Raydium swaps to inject an undisclosed SOL transfer, quietly routing fees to an attacker wallet.