Skip to content

Commit

Permalink
Install a Snap From NPM iOS
Browse files Browse the repository at this point in the history
- Create NPMLocation class
- Create a custom fetch function for the npm logic as we have slightly
  different logic
- create a swift native module to read a .tgz file and decompress it
- read the decompressed folder data and pass it to snaps
  • Loading branch information
owencraston committed Mar 23, 2023
1 parent d7adb30 commit dce223a
Show file tree
Hide file tree
Showing 16 changed files with 799 additions and 45 deletions.
6 changes: 3 additions & 3 deletions app/components/Views/Snaps/SnapsDev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import { createStyles } from './styles';
*
* local:http://localhost:3000/snap/
* local:http://localhost:3000/helloworldsnap/
* npm:@consensys/starknet-snap
* npm:@chainsafe/filsnap
*/

const SnapsDev = () => {
const navigation = useNavigation();
const { colors } = useTheme();

const [snapInput, setSnapInput] = useState<string>(
'local:http://localhost:3000/helloworldsnap/',
);
const [snapInput, setSnapInput] = useState<string>('npm:@chainsafe/filsnap');
const snaps = useSelector(
(state: any) => state.engine.backgroundState.SnapController.snaps,
);
Expand Down
7 changes: 1 addition & 6 deletions app/core/Snaps/SnapDuplex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,7 @@ export default abstract class SnapDuplex extends Duplex {

_write(data: StreamData, _encoding: string | null, cb: () => void): void {
// eslint-disable-next-line no-console
console.log(
'[SNAP DUPLEX LOG] SnapDuplex+_write: Job',
this._jobId,
'write data (keys)',
Object.keys(data.data),
);
console.log('[SNAP DUPLEX LOG] SnapDuplex+_write: Job', this._jobId);
this._stream.write({ data, jobId: this._jobId });
cb();
}
Expand Down
17 changes: 8 additions & 9 deletions app/core/Snaps/location/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
NpmSnapFileNames,
createSnapManifest,
normalizeRelative,
HttpSnapIdStruct,
} from '@metamask/snaps-utils';
import { assert, assertStruct } from '@metamask/utils';

import { SnapLocation } from './location';

Expand Down Expand Up @@ -37,8 +39,7 @@ export class HttpLocation implements SnapLocation {
private readonly fetchOptions?: RequestInit;

constructor(url: URL, opts: HttpOptions = {}) {
// TODO get the asserts working from @metamask/utils
// assertStruct(url.toString(), HttpSnapIdStruct, 'Invalid Snap Id: ');
assertStruct(url.toString(), HttpSnapIdStruct, 'Invalid Snap Id: ');
this.fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
this.fetchOptions = opts.fetchOptions;
this.url = url;
Expand Down Expand Up @@ -89,12 +90,11 @@ export class HttpLocation implements SnapLocation {
});

const blob = await response.text();
assert(
!this.cache.has(relativePath),
'Corrupted cache, multiple files with same path.',
);

//TODO: get the asserts working from @metamask/utils
// assert(
// !this.cache.has(relativePath),
// 'Corrupted cache, multiple files with same path.',
// );
this.cache.set(relativePath, { file: vfile, contents: blob });

return this.fetch(relativePath);
Expand All @@ -105,8 +105,7 @@ export class HttpLocation implements SnapLocation {
}

private toCanonical(path: string): URL {
// TODO get the asserts working from @metamask/utils
// assert(!path.startsWith('/'), 'Tried to parse absolute path.');
assert(!path.startsWith('/'), 'Tried to parse absolute path.');
return new URL(path, this.url.toString());
}
}
19 changes: 9 additions & 10 deletions app/core/Snaps/location/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ import {
SnapIdPrefixes,
SnapManifest,
VirtualFile,
LocalSnapIdStruct,
} from '@metamask/snaps-utils';

import { HttpLocation, HttpOptions } from './http';
import { SnapLocation } from './location';
import { assert, assertStruct } from '@metamask/utils';

export class LocalLocation implements SnapLocation {
readonly #http: HttpLocation;

constructor(url: URL, opts: HttpOptions = {}) {
// TODO get the asserts working from @metamask/utils
// assertStruct(url.toString(), LocalSnapIdStruct, 'Invalid Snap Id');
// // TODO(ritave): Write deepMerge() which merges fetchOptions.
// assert(
// opts.fetchOptions === undefined,
// 'Currently adding fetch options to local: is unsupported.',
// );
assertStruct(url.toString(), LocalSnapIdStruct, 'Invalid Snap Id');
// TODO(ritave): Write deepMerge() which merges fetchOptions.
assert(
opts.fetchOptions === undefined,
'Currently adding fetch options to local: is unsupported.',
);

this.#http = new HttpLocation(
new URL(url.toString().slice(SnapIdPrefixes.local.length)),
Expand Down Expand Up @@ -50,8 +50,7 @@ export class LocalLocation implements SnapLocation {
function convertCanonical<Result>(
vfile: VirtualFile<Result>,
): VirtualFile<Result> {
//TODO get the asserts working from @metamask/utils
// assert(vfile.data.canonicalPath !== undefined);
assert(vfile.data.canonicalPath !== undefined);
vfile.data.canonicalPath = `local:${vfile.data.canonicalPath}`;
return vfile;
}
21 changes: 6 additions & 15 deletions app/core/Snaps/location/location.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import { SemVerRange, SnapManifest, VirtualFile } from '@metamask/snaps-utils';
import { SnapManifest, VirtualFile } from '@metamask/snaps-utils';
import { LocalLocation } from './local';
import { NpmLocation, NpmOptions } from './npm';

export interface NpmOptions {
/**
* @default DEFAULT_REQUESTED_SNAP_VERSION
*/
versionRange?: SemVerRange;
/**
* Whether to allow custom NPM registries outside of {@link DEFAULT_NPM_REGISTRY}.
*
* @default false
*/
allowCustomRegistries?: boolean;
}

type DetectSnapLocationOptions = NpmOptions & {
export type DetectSnapLocationOptions = NpmOptions & {
/**
* The function used to fetch data.
*
Expand Down Expand Up @@ -48,6 +36,7 @@ export interface SnapLocation {
* @param opts - NPM options and feature flags.
* @returns SnapLocation based on url.
*/

export function detectSnapLocation(
location: string | URL,
opts?: DetectSnapLocationOptions,
Expand All @@ -56,6 +45,8 @@ export function detectSnapLocation(
switch (root.protocol) {
case 'local:':
return new LocalLocation(root, opts);
case 'npm:':
return new NpmLocation(root, opts);
default:
throw new TypeError(
`Unrecognized "${root.protocol}" snap location protocol.`,
Expand Down
Loading

0 comments on commit dce223a

Please sign in to comment.